@kne/fastify-file-manager 3.0.1-alpha.1 → 3.0.1-alpha.3

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.
@@ -13,6 +13,8 @@ module.exports = fp(async (fastify, fastifyOptions) => {
13
13
  const { models, services } = fastify.fileManager;
14
14
  const { Op } = fastify.sequelize.Sequelize;
15
15
 
16
+ const sanitizeFilename = filename => filename.replace(/[\\/:*?"<>|\0]/g, '_');
17
+
16
18
  const detail = async ({ id, uuid, namespace }) => {
17
19
  const file = await models.fileRecord.findOne({
18
20
  where: { uuid: String(id || uuid).split('?')[0] }
@@ -25,14 +27,14 @@ module.exports = fp(async (fastify, fastifyOptions) => {
25
27
  return file;
26
28
  };
27
29
  const uploadToFileSystem = async ({ id, file, namespace, options }) => {
28
- const { filename, encoding, mimetype } = file;
30
+ const { encoding, mimetype } = file;
31
+ const filename = sanitizeFilename(file.filename);
29
32
  const hash = crypto.createHash('md5');
30
33
  const extension = path.extname(filename);
31
34
  const tmpPath = path.resolve(os.tmpdir(), `temp_${filename}_${crypto.randomBytes(6).toString('hex')}`);
32
35
  let fileSize = 0;
33
36
  if (file.file) {
34
37
  const writeStream = fs.createWriteStream(tmpPath);
35
-
36
38
  await new Promise((resolve, reject) => {
37
39
  const cleanup = () => {
38
40
  file.file.removeAllListeners();
@@ -74,8 +76,15 @@ module.exports = fp(async (fastify, fastifyOptions) => {
74
76
  await fs.writeFile(tmpPath, buffer);
75
77
  fileSize = buffer.byteLength;
76
78
  } else if (file.filepath) {
79
+ const readStream = fs.createReadStream(file.filepath);
80
+ await new Promise((resolve, reject) => {
81
+ readStream.on('data', chunk => hash.update(chunk));
82
+ readStream.on('end', resolve);
83
+ readStream.on('error', reject);
84
+ });
77
85
  await fs.copy(file.filepath, tmpPath);
78
86
  const stat = await fs.stat(tmpPath);
87
+
79
88
  fileSize = stat.size;
80
89
  } else {
81
90
  throw new Error('文件类型不支持');
@@ -118,16 +127,18 @@ module.exports = fp(async (fastify, fastifyOptions) => {
118
127
  file.options = options;
119
128
  await file.save();
120
129
  return file;
121
- })(() => models.fileRecord.create({
122
- filename,
123
- namespace: namespace || fastifyOptions.namespace,
124
- encoding,
125
- mimetype,
126
- hash: digest,
127
- size: fileSize,
128
- storageType,
129
- options
130
- }));
130
+ })(() =>
131
+ models.fileRecord.create({
132
+ filename,
133
+ namespace: namespace || fastifyOptions.namespace,
134
+ encoding,
135
+ mimetype,
136
+ hash: digest,
137
+ size: fileSize,
138
+ storageType,
139
+ options
140
+ })
141
+ );
131
142
  return Object.assign({}, outputFile.get({ plain: true }), { id: outputFile.uuid });
132
143
  };
133
144
 
@@ -182,7 +193,10 @@ module.exports = fp(async (fastify, fastifyOptions) => {
182
193
  }
183
194
 
184
195
  const tempFile = {
185
- filename, mimetype: response.headers.get('content-type'), encoding: 'binary', file: nodeStream
196
+ filename: sanitizeFilename(filename),
197
+ mimetype: response.headers.get('content-type'),
198
+ encoding: 'binary',
199
+ file: nodeStream
186
200
  };
187
201
  return await uploadToFileSystem({ id, file: tempFile, namespace, options });
188
202
  };
@@ -217,7 +231,9 @@ module.exports = fp(async (fastify, fastifyOptions) => {
217
231
  targetFile = await ossServices.downloadFile({ filename: targetFileName });
218
232
  }
219
233
  return Object.assign({}, file.get({ pain: true }), {
220
- id: file.uuid, filePath: targetFileName, targetFile
234
+ id: file.uuid,
235
+ filePath: targetFileName,
236
+ targetFile
221
237
  });
222
238
  };
223
239
 
@@ -272,10 +288,14 @@ module.exports = fp(async (fastify, fastifyOptions) => {
272
288
  });
273
289
 
274
290
  const { count, rows } = await models.fileRecord.findAndCountAll({
275
- where: queryFilter, offset: perPage * (currentPage - 1), limit: perPage, order: [['createdAt', 'desc']]
291
+ where: queryFilter,
292
+ offset: perPage * (currentPage - 1),
293
+ limit: perPage,
294
+ order: [['createdAt', 'desc']]
276
295
  });
277
296
  return {
278
- pageData: rows.map(item => Object.assign({}, item.get({ plain: true }), { id: item.uuid })), totalCount: count
297
+ pageData: rows.map(item => Object.assign({}, item.get({ plain: true }), { id: item.uuid })),
298
+ totalCount: count
279
299
  };
280
300
  };
281
301
 
@@ -291,6 +311,10 @@ module.exports = fp(async (fastify, fastifyOptions) => {
291
311
 
292
312
  const renameFile = async ({ id, filename }) => {
293
313
  const file = await detail({ id });
314
+ filename = sanitizeFilename(filename);
315
+ if (!path.extname(filename) && path.extname(file.filename)) {
316
+ filename += path.extname(file.filename);
317
+ }
294
318
  file.filename = filename;
295
319
  await file.save();
296
320
  };
@@ -320,7 +344,8 @@ module.exports = fp(async (fastify, fastifyOptions) => {
320
344
  }
321
345
 
322
346
  return Object.assign({}, file.get({ plain: true }), {
323
- id: file.uuid, buffer
347
+ id: file.uuid,
348
+ buffer
324
349
  });
325
350
  };
326
351
 
@@ -396,7 +421,8 @@ module.exports = fp(async (fastify, fastifyOptions) => {
396
421
  const tmpPath = path.resolve(os.tmpdir(), `temp_${id}_${crypto.randomBytes(6).toString('hex')}`);
397
422
  await compressing[type].uncompress(fileStream, tmpPath);
398
423
  const files = await glob(globOptions, {
399
- cwd: tmpPath, nodir: true
424
+ cwd: tmpPath,
425
+ nodir: true
400
426
  });
401
427
  //将文件上传到文件系统
402
428
  const fileList = [];
@@ -406,11 +432,17 @@ module.exports = fp(async (fastify, fastifyOptions) => {
406
432
  const mimetype = MimeTypes.lookup(filepath) || 'application/octet-stream';
407
433
  const file = await uploadToFileSystem({
408
434
  file: {
409
- filename, mimetype, encoding: 'binary', filepath
410
- }, filename, namespace
435
+ filename,
436
+ mimetype,
437
+ encoding: 'binary',
438
+ filepath
439
+ },
440
+ filename,
441
+ namespace
411
442
  });
412
443
  fileList.push({
413
- dir, file
444
+ dir,
445
+ file
414
446
  });
415
447
  }
416
448
  fs.remove(tmpPath).catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kne/fastify-file-manager",
3
- "version": "3.0.1-alpha.1",
3
+ "version": "3.0.1-alpha.3",
4
4
  "description": "用于管理静态文件上传查看等",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -8,7 +8,8 @@
8
8
  "build:md": "npx @kne/md-doc",
9
9
  "start:md": "npx @kne/md-doc --watch",
10
10
  "prettier": "prettier --config .prettierrc --write '{libs/**/*,index}.{js,jsx,ts,tsx,json,css,scss}'",
11
- "lint-staged": "npx lint-staged"
11
+ "lint-staged": "npx lint-staged",
12
+ "test": "mocha tests/**/*.test.js --timeout 30000"
12
13
  },
13
14
  "lint-staged": {
14
15
  "{libs/**/*,index}.{js,jsx,ts,tsx,json,css,scss}": [
@@ -37,6 +38,7 @@
37
38
  "@kne/fastify-sequelize": "^2.0.1",
38
39
  "fastify": "^5.3.2",
39
40
  "husky": "^9.0.11",
41
+ "mocha": "^11.7.5",
40
42
  "prettier": "^3.2.5",
41
43
  "qs": "^6.12.3",
42
44
  "sqlite3": "^5.1.7"