This commit is contained in:
otofune 2017-11-14 03:47:42 +09:00
parent 64aedcaa6b
commit e56f716a89
2 changed files with 65 additions and 65 deletions

View file

@ -18,10 +18,10 @@ const log = debug('misskey:register-drive-file');
const tmpFile = (): Promise<string> => new Promise((resolve, reject) => { const tmpFile = (): Promise<string> => new Promise((resolve, reject) => {
tmp.file((e, path) => { tmp.file((e, path) => {
if (e) return reject(e) if (e) return reject(e);
resolve(path) resolve(path);
}) });
}) });
const addToGridFS = (name: string, readable: stream.Readable, type: string, metadata: any): Promise<any> => const addToGridFS = (name: string, readable: stream.Readable, type: string, metadata: any): Promise<any> =>
getGridFSBucket() getGridFSBucket()
@ -30,7 +30,7 @@ const addToGridFS = (name: string, readable: stream.Readable, type: string, meta
writeStream.once('finish', (doc) => { resolve(doc); }); writeStream.once('finish', (doc) => { resolve(doc); });
writeStream.on('error', reject); writeStream.on('error', reject);
readable.pipe(writeStream); readable.pipe(writeStream);
})) }));
/** /**
* Add file to drive * Add file to drive
@ -56,76 +56,76 @@ export default (
// Get file path // Get file path
new Promise((res: (v: string) => void, rej) => { new Promise((res: (v: string) => void, rej) => {
if (typeof file === 'string') { if (typeof file === 'string') {
res(file) res(file);
return return;
} }
if (file instanceof Buffer) { if (file instanceof Buffer) {
tmpFile() tmpFile()
.then(path => { .then(path => {
fs.writeFile(path, file, (err) => { fs.writeFile(path, file, (err) => {
if (err) rej(err) if (err) rej(err);
res(path) res(path);
});
}) })
}) .catch(rej);
.catch(rej) return;
return
} }
if (typeof file === 'object' && typeof file.read === 'function') { if (typeof file === 'object' && typeof file.read === 'function') {
tmpFile() tmpFile()
.then(path => { .then(path => {
const readable: stream.Readable = file const readable: stream.Readable = file;
const writable = fs.createWriteStream(path) const writable = fs.createWriteStream(path);
readable readable
.on('error', rej) .on('error', rej)
.on('end', () => { .on('end', () => {
res(path) res(path);
}) })
.pipe(writable) .pipe(writable)
.on('error', rej) .on('error', rej);
}) })
.catch(rej) .catch(rej);
} }
rej(new Error('un-compatible file.')) rej(new Error('un-compatible file.'));
}) })
// Calculate hash, get content type and get file size // Calculate hash, get content type and get file size
.then(path => Promise.all([ .then(path => Promise.all([
path, path,
// hash // hash
((): Promise<string> => new Promise((res, rej) => { ((): Promise<string> => new Promise((res, rej) => {
const readable = fs.createReadStream(path) const readable = fs.createReadStream(path);
const hash = crypto.createHash('md5') const hash = crypto.createHash('md5');
readable readable
.on('error', rej) .on('error', rej)
.on('end', () => { .on('end', () => {
res(hash.digest('hex')) res(hash.digest('hex'));
}) })
.pipe(hash) .pipe(hash)
.on('error', rej) .on('error', rej);
}))(), }))(),
// mime // mime
((): Promise<[string, string | null]> => new Promise((res, rej) => { ((): Promise<[string, string | null]> => new Promise((res, rej) => {
const readable = fs.createReadStream(path) const readable = fs.createReadStream(path);
readable readable
.on('error', rej) .on('error', rej)
.once('data', (buffer: Buffer) => { .once('data', (buffer: Buffer) => {
readable.destroy() readable.destroy();
const type = fileType(buffer) const type = fileType(buffer);
if (!type) { if (!type) {
return res(['application/octet-stream', null]) return res(['application/octet-stream', null]);
} }
return res([type.mime, type.ext]) return res([type.mime, type.ext]);
}) });
}))(), }))(),
// size // size
((): Promise<number> => new Promise((res, rej) => { ((): Promise<number> => new Promise((res, rej) => {
fs.stat(path, (err, stats) => { fs.stat(path, (err, stats) => {
if (err) return rej(err) if (err) return rej(err);
res(stats.size) res(stats.size);
}) });
}))() }))()
])) ]))
.then(async ([path, hash, [mime, ext], size]) => { .then(async ([path, hash, [mime, ext], size]) => {
log(`hash: ${hash}, mime: ${mime}, ext: ${ext}, size: ${size}`) log(`hash: ${hash}, mime: ${mime}, ext: ${ext}, size: ${size}`);
// detect name // detect name
const detectedName: string = name || (ext ? `untitled.${ext}` : 'untitled'); const detectedName: string = name || (ext ? `untitled.${ext}` : 'untitled');
@ -149,7 +149,7 @@ export default (
// properties // properties
(async () => { (async () => {
if (!/^image\/.*$/.test(mime)) { if (!/^image\/.*$/.test(mime)) {
return null return null;
} }
// If the file is an image, calculate width and height to save in property // If the file is an image, calculate width and height to save in property
const g = gm(data, name); const g = gm(data, name);
@ -159,21 +159,21 @@ export default (
height: size.height height: size.height
}; };
log('image width and height is calculated'); log('image width and height is calculated');
return properties return properties;
})(), })(),
// folder // folder
(async () => { (async () => {
if (!folderId) { if (!folderId) {
return null return null;
} }
const driveFolder = await DriveFolder.findOne({ const driveFolder = await DriveFolder.findOne({
_id: folderId, _id: folderId,
user_id: user._id user_id: user._id
}) });
if (!driveFolder) { if (!driveFolder) {
throw 'folder-not-found' throw 'folder-not-found';
} }
return driveFolder return driveFolder;
})(), })(),
// usage checker // usage checker
(async () => { (async () => {
@ -195,9 +195,9 @@ export default (
]) ])
.then((aggregates: any[]) => { .then((aggregates: any[]) => {
if (aggregates.length > 0) { if (aggregates.length > 0) {
return aggregates[0].usage return aggregates[0].usage;
} }
return 0 return 0;
}); });
log(`drive usage is ${usage}`); log(`drive usage is ${usage}`);
@ -207,21 +207,21 @@ export default (
throw 'no-free-space'; throw 'no-free-space';
} }
})() })()
]) ]);
const readable = fs.createReadStream(path) const readable = fs.createReadStream(path);
return addToGridFS(name, readable, mime, { return addToGridFS(name, readable, mime, {
user_id: user._id, user_id: user._id,
folder_id: folder !== null ? folder._id : null, folder_id: folder !== null ? folder._id : null,
comment: comment, comment: comment,
properties: properties properties: properties
}) });
}) })
.then(file => { .then(file => {
log(`drive file has been created ${file._id}`); log(`drive file has been created ${file._id}`);
resolve(file) resolve(file);
return serialize(file) return serialize(file);
}) })
.then(serializedFile => { .then(serializedFile => {
// Publish drive_file_created event // Publish drive_file_created event
@ -241,5 +241,5 @@ export default (
}); });
} }
}) })
.catch(reject) .catch(reject);
}); });

View file

@ -12,7 +12,7 @@ import * as fs from 'fs';
import * as request from 'request'; import * as request from 'request';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
const log = debug('misskey:endpoint:upload_from_url') const log = debug('misskey:endpoint:upload_from_url');
/** /**
* Create a file from a URL * Create a file from a URL
@ -39,54 +39,54 @@ module.exports = (params, user) => new Promise((res, rej) => {
// Create temp file // Create temp file
new Promise((res, rej) => { new Promise((res, rej) => {
tmp.file((e, path) => { tmp.file((e, path) => {
if (e) return rej(e) if (e) return rej(e);
res(path) res(path);
}) });
}) })
// Download file // Download file
.then((path: string) => new Promise((res, rej) => { .then((path: string) => new Promise((res, rej) => {
const writable = fs.createWriteStream(path) const writable = fs.createWriteStream(path);
request(url) request(url)
.on('error', rej) .on('error', rej)
.on('end', () => { .on('end', () => {
writable.close() writable.close();
res(path) res(path);
}) })
.pipe(writable) .pipe(writable)
.on('error', rej) .on('error', rej);
})) }))
// Calculate hash & content-type // Calculate hash & content-type
.then((path: string) => new Promise((res, rej) => { .then((path: string) => new Promise((res, rej) => {
const readable = fs.createReadStream(path) const readable = fs.createReadStream(path);
const hash = crypto.createHash('md5') const hash = crypto.createHash('md5');
readable readable
.on('error', rej) .on('error', rej)
.on('end', () => { .on('end', () => {
hash.end() hash.end();
res([path, hash.digest('hex')]) res([path, hash.digest('hex')]);
}) })
.pipe(hash) .pipe(hash)
.on('error', rej) .on('error', rej);
})) }))
// Create file // Create file
.then((rv: string[]) => new Promise((res, rej) => { .then((rv: string[]) => new Promise((res, rej) => {
const [path, hash] = rv const [path, hash] = rv;
create(user, { create(user, {
stream: fs.createReadStream(path), stream: fs.createReadStream(path),
name, name,
hash hash
}, null, folderId) }, null, folderId)
.then(driveFile => { .then(driveFile => {
res(driveFile) res(driveFile);
// crean-up // crean-up
fs.unlink(path, (e) => { fs.unlink(path, (e) => {
if (e) log(e.stack) if (e) log(e.stack);
});
}) })
}) .catch(rej);
.catch(rej)
})) }))
// Serialize // Serialize
.then(serialize) .then(serialize)
.then(res) .then(res)
.catch(rej) .catch(rej);
}); });