1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
const fs = require('fs');
const path = require('path');
const blake3 = require('blake3');
const jetpack = require('fs-jetpack');
const FileType = require('file-type');
function DiskStorage(opts) {
this.getFilename = opts.filename;
if (typeof opts.destination === 'string') {
jetpack.dir(opts.destination);
this.getDestination = ($0, $1, cb) => { cb(null, opts.destination); };
} else {
this.getDestination = opts.destination;
}
}
DiskStorage.prototype._handleFile = function _handleFile(req, file, cb) {
const that = this; // eslint-disable-line consistent-this
that.getDestination(req, file, (err, destination) => {
if (err) return cb(err);
that.getFilename(req, file, (err, filename) => {
if (err) return cb(err);
const finalPath = path.join(destination, filename);
const onerror = err => {
hash.dispose(); // eslint-disable-line no-use-before-define
cb(err);
};
let outStream;
let hash;
if (file._isChunk) {
if (!file._chunksData.stream) {
file._chunksData.stream = fs.createWriteStream(finalPath, { flags: 'a' });
file._chunksData.stream.on('error', onerror);
}
if (!file._chunksData.hasher) {
file._chunksData.hasher = blake3.createHash();
}
outStream = file._chunksData.stream;
hash = file._chunksData.hasher;
} else {
outStream = fs.createWriteStream(finalPath);
outStream.on('error', onerror);
hash = blake3.createHash();
}
file.stream.on('error', onerror);
file.stream.on('data', d => hash.update(d));
if (file._isChunk) {
if (file._chunksData.chunks === 0) {
FileType.stream(file.stream).then(ftStream => {
file._chunksData.fileType = ftStream.fileType;
file.stream.on('end', () => {
cb(null, {
destination,
filename,
path: finalPath,
fileType: file._chunksData.fileType
});
});
ftStream.pipe(outStream, { end: false });
});
} else {
file.stream.on('end', () => {
cb(null, {
destination,
filename,
path: finalPath,
fileType: file._chunksData.fileType
});
});
file.stream.pipe(outStream, { end: false });
}
} else {
FileType.stream(file.stream).then(ftStream => {
outStream.on('finish', () => {
cb(null, {
destination,
filename,
path: finalPath,
size: outStream.bytesWritten,
hash: hash.digest('hex'),
fileType: ftStream.fileType
});
});
ftStream.pipe(outStream);
});
}
});
});
};
DiskStorage.prototype._removeFile = function _removeFile(req, file, cb) {
const path = file.path;
delete file.destination;
delete file.filename;
delete file.path;
fs.unlink(path, cb);
};
module.exports = opts => new DiskStorage(opts);
|