* Added an API endpoint to check the existence of the file * fix #2773: Now we can prevent users from posting the same images * bug fix
This commit is contained in:
parent
d0570d7fe3
commit
3e897727ca
3 changed files with 106 additions and 34 deletions
8
src/client/app/common/scripts/get-md5.ts
Normal file
8
src/client/app/common/scripts/get-md5.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
export default (data: ArrayBuffer) => {
|
||||||
|
const buf = new Buffer(data);
|
||||||
|
const hash = crypto.createHash("md5");
|
||||||
|
hash.update(buf);
|
||||||
|
return hash.digest("hex");
|
||||||
|
};
|
|
@ -20,6 +20,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { apiUrl } from '../../../config';
|
import { apiUrl } from '../../../config';
|
||||||
|
import getMD5 from '../../scripts/get-md5';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
data() {
|
data() {
|
||||||
|
@ -28,27 +29,49 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
upload(file, folder) {
|
checkExistence(fileData: ArrayBuffer): Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const data = new FormData();
|
||||||
|
data.append('md5', getMD5(fileData));
|
||||||
|
|
||||||
|
(this as any).api('drive/files/check_existence', {
|
||||||
|
md5: getMD5(fileData)
|
||||||
|
}).then(resp => {
|
||||||
|
resolve(resp.file);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
upload(file: File, folder: any) {
|
||||||
if (folder && typeof folder == 'object') folder = folder.id;
|
if (folder && typeof folder == 'object') folder = folder.id;
|
||||||
|
|
||||||
const id = Math.random();
|
const id = Math.random();
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e: any) => {
|
||||||
|
this.checkExistence(e.target.result).then(result => {
|
||||||
|
console.log(result);
|
||||||
|
if (result !== null) {
|
||||||
|
this.$emit('uploaded', result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload if the file didn't exist yet
|
||||||
|
const buf = new Uint8Array(e.target.result);
|
||||||
|
let bin = "";
|
||||||
|
// We use for-of loop instead of apply() to avoid RangeError
|
||||||
|
// SEE: https://stackoverflow.com/questions/9267899/arraybuffer-to-base64-encoded-string
|
||||||
|
for (const byte of buf) bin += String.fromCharCode(byte);
|
||||||
const ctx = {
|
const ctx = {
|
||||||
id: id,
|
id: id,
|
||||||
name: file.name || 'untitled',
|
name: file.name || 'untitled',
|
||||||
progress: undefined,
|
progress: undefined,
|
||||||
img: undefined
|
img: 'data:*/*;base64,' + btoa(bin)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.uploads.push(ctx);
|
this.uploads.push(ctx);
|
||||||
this.$emit('change', this.uploads);
|
this.$emit('change', this.uploads);
|
||||||
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = (e: any) => {
|
|
||||||
ctx.img = e.target.result;
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
|
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
data.append('i', this.$store.state.i.token);
|
data.append('i', this.$store.state.i.token);
|
||||||
data.append('file', file);
|
data.append('file', file);
|
||||||
|
@ -75,6 +98,9 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.send(data);
|
xhr.send(data);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
reader.readAsArrayBuffer(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
38
src/server/api/endpoints/drive/files/check_existence.ts
Normal file
38
src/server/api/endpoints/drive/files/check_existence.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import $ from 'cafy';
|
||||||
|
import DriveFile, { pack } from '../../../../../models/drive-file';
|
||||||
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '与えられたMD5ハッシュ値を持つファイルがドライブに存在するかどうかを返します。',
|
||||||
|
'en-US': 'Returns whether the file with the given MD5 hash exists in the user\'s drive.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: true,
|
||||||
|
|
||||||
|
kind: 'drive-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
md5: $.str.note({
|
||||||
|
desc: {
|
||||||
|
'ja-JP': 'ファイルのMD5ハッシュ'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
|
const [md5, md5Err] = $.str.get(params.md5);
|
||||||
|
if (md5Err) return rej('invalid md5 param');
|
||||||
|
|
||||||
|
const file = await DriveFile.findOne({
|
||||||
|
md5: md5,
|
||||||
|
'metadata.userId': user._id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (file === null) {
|
||||||
|
res({ file: null });
|
||||||
|
} else {
|
||||||
|
res({ file: await pack(file) });
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in a new issue