@kne/fastify-file-manager 2.0.13 → 3.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -27,13 +27,21 @@ module.exports = ({ DataTypes }) => {
|
|
|
27
27
|
type: DataTypes.STRING,
|
|
28
28
|
allowNull: false,
|
|
29
29
|
comment: '存储类型:local本地文件系统,oss远程oss存储'
|
|
30
|
+
},
|
|
31
|
+
options: {
|
|
32
|
+
type: DataTypes.JSONB,
|
|
33
|
+
defaultValue: {},
|
|
34
|
+
comment: '扩展字段'
|
|
30
35
|
}
|
|
31
36
|
},
|
|
32
37
|
options: {
|
|
33
38
|
indexes: [
|
|
34
39
|
{
|
|
35
40
|
unique: true,
|
|
36
|
-
fields: ['uuid',
|
|
41
|
+
fields: ['uuid'],
|
|
42
|
+
where: {
|
|
43
|
+
deleted_at: null
|
|
44
|
+
}
|
|
37
45
|
},
|
|
38
46
|
{
|
|
39
47
|
fields: ['namespace']
|
|
@@ -6,12 +6,13 @@ const { NotFound } = require('http-errors');
|
|
|
6
6
|
const os = require('node:os');
|
|
7
7
|
const { Readable } = require('node:stream');
|
|
8
8
|
const compressing = require('compressing');
|
|
9
|
+
const { glob } = require('glob');
|
|
9
10
|
|
|
10
11
|
module.exports = fp(async (fastify, options) => {
|
|
11
12
|
const { models, services } = fastify.fileManager;
|
|
12
13
|
const { Op } = fastify.sequelize.Sequelize;
|
|
13
14
|
|
|
14
|
-
const detail = async ({ id, uuid }) => {
|
|
15
|
+
const detail = async ({ id, uuid, namespace }) => {
|
|
15
16
|
const file = await models.fileRecord.findOne({
|
|
16
17
|
where: { uuid: String(id || uuid).split('?')[0] }
|
|
17
18
|
});
|
|
@@ -22,7 +23,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
22
23
|
|
|
23
24
|
return file;
|
|
24
25
|
};
|
|
25
|
-
const uploadToFileSystem = async ({ id, file, namespace }) => {
|
|
26
|
+
const uploadToFileSystem = async ({ id, file, namespace, options }) => {
|
|
26
27
|
const { filename, encoding, mimetype } = file;
|
|
27
28
|
const hash = crypto.createHash('md5');
|
|
28
29
|
const extension = path.extname(filename);
|
|
@@ -94,6 +95,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
94
95
|
file.hash = digest;
|
|
95
96
|
file.size = fileSize;
|
|
96
97
|
file.storageType = storageType;
|
|
98
|
+
file.options = options;
|
|
97
99
|
await file.save();
|
|
98
100
|
return file;
|
|
99
101
|
})(() =>
|
|
@@ -104,13 +106,14 @@ module.exports = fp(async (fastify, options) => {
|
|
|
104
106
|
mimetype,
|
|
105
107
|
hash: digest,
|
|
106
108
|
size: fileSize,
|
|
107
|
-
storageType
|
|
109
|
+
storageType,
|
|
110
|
+
options
|
|
108
111
|
})
|
|
109
112
|
);
|
|
110
113
|
return Object.assign({}, outputFile.get({ plain: true }), { id: outputFile.uuid });
|
|
111
114
|
};
|
|
112
115
|
|
|
113
|
-
const uploadFromUrl = async ({ id, url, filename: originFilename, namespace }) => {
|
|
116
|
+
const uploadFromUrl = async ({ id, url, filename: originFilename, namespace, options }) => {
|
|
114
117
|
const response = await fetch(url);
|
|
115
118
|
if (!response.ok) {
|
|
116
119
|
throw new Error('下载文件失败');
|
|
@@ -166,11 +169,11 @@ module.exports = fp(async (fastify, options) => {
|
|
|
166
169
|
encoding: 'binary',
|
|
167
170
|
file: nodeStream
|
|
168
171
|
};
|
|
169
|
-
return await uploadToFileSystem({ id, file: tempFile, namespace });
|
|
172
|
+
return await uploadToFileSystem({ id, file: tempFile, namespace, options });
|
|
170
173
|
};
|
|
171
174
|
|
|
172
175
|
const getFileUrl = async ({ id, namespace }) => {
|
|
173
|
-
const file = await detail({ id });
|
|
176
|
+
const file = await detail({ id, namespace });
|
|
174
177
|
const extension = path.extname(file.filename);
|
|
175
178
|
const ossServices = options.ossAdapter();
|
|
176
179
|
if (file.storageType === 'oss' && typeof ossServices.getFileLink !== 'function') {
|
|
@@ -186,8 +189,8 @@ module.exports = fp(async (fastify, options) => {
|
|
|
186
189
|
return `${options.prefix}/file/${file.hash}${extension}?filename=${file.filename}`;
|
|
187
190
|
};
|
|
188
191
|
|
|
189
|
-
const getFileInfo = async ({ id }) => {
|
|
190
|
-
const file = await detail({ id });
|
|
192
|
+
const getFileInfo = async ({ id, namespace }) => {
|
|
193
|
+
const file = await detail({ id, namespace });
|
|
191
194
|
const extension = path.extname(file.filename);
|
|
192
195
|
const targetFileName = `${file.hash}${extension}`;
|
|
193
196
|
const ossServices = options.ossAdapter();
|
|
@@ -205,8 +208,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
205
208
|
});
|
|
206
209
|
};
|
|
207
210
|
|
|
208
|
-
const getFileList = async ({ filter = {}, currentPage, perPage }) => {
|
|
209
|
-
// namespace: namespace || options.namespace
|
|
211
|
+
const getFileList = async ({ filter = {}, namespace, currentPage, perPage }) => {
|
|
210
212
|
const queryFilter = {};
|
|
211
213
|
|
|
212
214
|
if (filter?.filename) {
|
|
@@ -228,30 +230,33 @@ module.exports = fp(async (fastify, options) => {
|
|
|
228
230
|
[Op.like]: `%${filter.namespace}%`
|
|
229
231
|
};
|
|
230
232
|
}
|
|
233
|
+
if (namespace) {
|
|
234
|
+
queryFilter.namespace = namespace;
|
|
235
|
+
}
|
|
231
236
|
|
|
232
237
|
if (filter?.id) {
|
|
233
|
-
queryFilter.uuid =
|
|
234
|
-
[Op.like]: `%${filter.id}%`
|
|
235
|
-
};
|
|
238
|
+
queryFilter.uuid = filter.id;
|
|
236
239
|
}
|
|
237
240
|
|
|
238
|
-
|
|
239
|
-
if (filter
|
|
240
|
-
|
|
241
|
-
[
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
[
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
[
|
|
252
|
-
|
|
241
|
+
['createdAt', 'updatedAt'].forEach(name => {
|
|
242
|
+
if (filter?.[name]) {
|
|
243
|
+
if (filter[name].startTime && filter[name].endTime) {
|
|
244
|
+
queryFilter[name] = {
|
|
245
|
+
[Op.between]: [filter[name].startTime, filter[name].endTime]
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
if (filter[name].startTime && !filter[name].endTime) {
|
|
249
|
+
queryFilter[name] = {
|
|
250
|
+
[Op.gte]: filter[name].startTime
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
if (!filter[name].startTime && filter[name].endTime) {
|
|
254
|
+
queryFilter[name] = {
|
|
255
|
+
[Op.lte]: filter[name].endTime
|
|
256
|
+
};
|
|
257
|
+
}
|
|
253
258
|
}
|
|
254
|
-
}
|
|
259
|
+
});
|
|
255
260
|
|
|
256
261
|
const { count, rows } = await models.fileRecord.findAndCountAll({
|
|
257
262
|
where: queryFilter,
|
|
@@ -281,8 +286,8 @@ module.exports = fp(async (fastify, options) => {
|
|
|
281
286
|
await file.save();
|
|
282
287
|
};
|
|
283
288
|
|
|
284
|
-
const getFileBlob = async ({ id }) => {
|
|
285
|
-
const file = await detail({ id });
|
|
289
|
+
const getFileBlob = async ({ id, namespace }) => {
|
|
290
|
+
const file = await detail({ id, namespace });
|
|
286
291
|
if (!file) {
|
|
287
292
|
throw new Error('文件不存在');
|
|
288
293
|
}
|
|
@@ -376,6 +381,38 @@ module.exports = fp(async (fastify, options) => {
|
|
|
376
381
|
});
|
|
377
382
|
};
|
|
378
383
|
|
|
384
|
+
//文件解压缩
|
|
385
|
+
const uncompressFile = async ({ id, type = 'zip', namespace, globOptions = '**/*' }) => {
|
|
386
|
+
const file = await detail({ id });
|
|
387
|
+
const fileStream = await getFileReadStream(file);
|
|
388
|
+
const tmpPath = path.resolve(os.tmpdir(), `temp_${id}_${crypto.randomBytes(6).toString('hex')}`);
|
|
389
|
+
await compressing[type].uncompress(fileStream, tmpPath);
|
|
390
|
+
const files = await glob(globOptions, {
|
|
391
|
+
cwd: tmpPath
|
|
392
|
+
});
|
|
393
|
+
//将文件上传到文件系统
|
|
394
|
+
const fileList = await Promise.all(
|
|
395
|
+
files.map(async dir => {
|
|
396
|
+
const filepath = path.resolve(tmpPath, dir);
|
|
397
|
+
const filename = path.basename(dir);
|
|
398
|
+
const fileStream = fs.createReadStream(filepath);
|
|
399
|
+
const file = await uploadToFileSystem({
|
|
400
|
+
file: fileStream,
|
|
401
|
+
filename,
|
|
402
|
+
namespace
|
|
403
|
+
});
|
|
404
|
+
return {
|
|
405
|
+
dir,
|
|
406
|
+
file
|
|
407
|
+
};
|
|
408
|
+
})
|
|
409
|
+
);
|
|
410
|
+
//清除临时文件
|
|
411
|
+
await fs.remove(tmpPath);
|
|
412
|
+
|
|
413
|
+
return fileList;
|
|
414
|
+
};
|
|
415
|
+
|
|
379
416
|
const getFileInstance = async ({ id, uuid }) => {
|
|
380
417
|
return detail({ id, uuid });
|
|
381
418
|
};
|
|
@@ -393,6 +430,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
393
430
|
getFileReadStream,
|
|
394
431
|
getCompressFileStream,
|
|
395
432
|
getCompressFileBlob,
|
|
433
|
+
uncompressFile,
|
|
396
434
|
getFileInstance, // 兼容之前api,后面可能会删掉
|
|
397
435
|
fileRecord: {
|
|
398
436
|
uploadToFileSystem,
|
|
@@ -407,6 +445,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
407
445
|
getFileReadStream,
|
|
408
446
|
getCompressFileStream,
|
|
409
447
|
getCompressFileBlob,
|
|
448
|
+
uncompressFile,
|
|
410
449
|
getFileInstance
|
|
411
450
|
}
|
|
412
451
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kne/fastify-file-manager",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.0",
|
|
4
4
|
"description": "用于管理静态文件上传查看等",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"@fastify/static": "^8.1.1",
|
|
52
52
|
"compressing": "^2.0.0",
|
|
53
53
|
"fs-extra": "^11.2.0",
|
|
54
|
+
"glob": "^13.0.0",
|
|
54
55
|
"http-errors": "^2.0.0"
|
|
55
56
|
}
|
|
56
57
|
}
|