@kne/fastify-file-manager 2.0.7 → 2.0.9

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.
@@ -5,6 +5,7 @@ const path = require('node:path');
5
5
  const { NotFound } = require('http-errors');
6
6
  const os = require('node:os');
7
7
  const { Readable } = require('node:stream');
8
+ const compressing = require('compressing');
8
9
 
9
10
  module.exports = fp(async (fastify, options) => {
10
11
  const { models, services } = fastify.fileManager;
@@ -29,7 +30,7 @@ module.exports = fp(async (fastify, options) => {
29
30
  const writeStream = fs.createWriteStream(tmpPath);
30
31
  let fileSize = 0;
31
32
  if (file.file) {
32
- file.file.on('data', (chunk) => {
33
+ file.file.on('data', chunk => {
33
34
  hash.update(chunk); // 更新哈希
34
35
  writeStream.write(chunk); // 写入文件
35
36
  fileSize += chunk.length; // 更新文件大小
@@ -73,14 +74,12 @@ module.exports = fp(async (fastify, options) => {
73
74
  const writeStream = fs.createWriteStream(filepath);
74
75
  const readStream = fs.createReadStream(tmpPath);
75
76
  await new Promise((resolve, reject) => {
76
- readStream.pipe(writeStream)
77
- .on('finish', resolve)
78
- .on('error', reject);
77
+ readStream.pipe(writeStream).on('finish', resolve).on('error', reject);
79
78
  });
80
79
  storageType = 'local';
81
80
  }
82
81
 
83
- //清楚临时文件
82
+ //清除临时文件
84
83
  await fs.remove(tmpPath);
85
84
 
86
85
  const outputFile = await (async create => {
@@ -128,12 +127,28 @@ module.exports = fp(async (fastify, options) => {
128
127
  nodeStream.emit('error', err);
129
128
  }
130
129
  };
131
- readChunk();
130
+ readChunk().catch(err => {
131
+ throw err;
132
+ });
133
+
134
+ let filename = path.basename(url).split('?')[0];
135
+
136
+ const contentDisposition = response.headers.get('content-disposition');
137
+
138
+ if (contentDisposition) {
139
+ const filenameMatch = contentDisposition.match(/filename="?(.+)"?/i);
140
+ if (filenameMatch && filenameMatch[1]) {
141
+ filename = filenameMatch[1];
142
+ }
143
+ }
144
+
145
+ const searchParams = new URLSearchParams(url.split('?')[1]);
146
+ if (searchParams.get('filename')) {
147
+ filename = searchParams.get('filename');
148
+ }
149
+
132
150
  const tempFile = {
133
- filename: path.basename(url).split('?')[0],
134
- mimetype: response.headers.get('content-type'),
135
- encoding: 'binary',
136
- file: nodeStream
151
+ filename, mimetype: response.headers.get('content-type'), encoding: 'binary', file: nodeStream
137
152
  };
138
153
  return await uploadToFileSystem({ id, file: tempFile, namespace });
139
154
  };
@@ -208,7 +223,7 @@ module.exports = fp(async (fastify, options) => {
208
223
  await models.fileRecord.destroy({
209
224
  where: {
210
225
  uuid: {
211
- [Op.in]: ids.map((str) => str.split('?')[0])
226
+ [Op.in]: ids.map(str => str.split('?')[0])
212
227
  }
213
228
  }
214
229
  });
@@ -249,27 +264,71 @@ module.exports = fp(async (fastify, options) => {
249
264
  });
250
265
  };
251
266
 
252
- const getFileStream = async ({ id }) => {
253
- const file = await detail({ id });
254
-
267
+ const getFileReadStream = file => {
255
268
  const extension = path.extname(file.filename);
256
269
  const targetFileName = `${file.hash}${extension}`;
257
270
  const ossServices = options.ossAdapter();
258
-
259
271
  if (file.storageType === 'oss') {
260
272
  if (typeof ossServices.getFileStream !== 'function') {
261
273
  throw new Error('ossAdapter未正确配置无法读取oss类型存储文件');
262
274
  }
263
- return await ossServices.getFileStream({ filename: targetFileName });
275
+ return ossServices.getFileStream({ filename: targetFileName });
264
276
  } else {
265
277
  const filePath = path.resolve(options.root, targetFileName);
266
- if (!(await fs.exists(filePath))) {
267
- throw new NotFound();
268
- }
269
278
  return fs.createReadStream(filePath);
270
279
  }
271
280
  };
272
281
 
282
+ const getFileStream = async ({ id }) => {
283
+ const file = await detail({ id });
284
+ return getFileReadStream(file);
285
+ };
286
+
287
+ const getCompressFileStream = async ({ ids, type = 'zip' }) => {
288
+ const fileList = await models.fileRecord.findAll({
289
+ where: {
290
+ uuid: {
291
+ [Op.in]: ids.map(str => str.split('?')[0])
292
+ }
293
+ }
294
+ });
295
+ const tmpPath = path.resolve(os.tmpdir(), `temp_compress_file_${crypto.randomBytes(6).toString('hex')}`);
296
+ await fs.mkdir(tmpPath);
297
+ const files = [];
298
+ for (const file of fileList) {
299
+ const filepath = path.resolve(tmpPath, file.filename);
300
+ const writeStream = fs.createWriteStream(filepath);
301
+ const fileStream = getFileReadStream(file);
302
+ fileStream.pipe(writeStream);
303
+ await new Promise((resolve, reject) => {
304
+ writeStream.on('finish', resolve);
305
+ writeStream.on('error', reject);
306
+ });
307
+ files.push(filepath);
308
+ }
309
+ const compressStream = new compressing[type].Stream();
310
+ files.forEach(filepath => {
311
+ compressStream.addEntry(path.resolve(filepath));
312
+ });
313
+ compressStream.on('error', () => {
314
+ fs.remove(tmpPath);
315
+ });
316
+ compressStream.on('end', () => {
317
+ fs.remove(tmpPath);
318
+ });
319
+ return compressStream;
320
+ };
321
+
322
+ const getCompressFileBlob = async (...args) => {
323
+ const compressStream = await getCompressFileStream(...args);
324
+ const chunks = [];
325
+ return new Promise((resolve, reject) => {
326
+ compressStream.on('data', chunk => chunks.push(chunk));
327
+ compressStream.on('end', () => resolve(Buffer.concat(chunks)));
328
+ compressStream.on('error', reject);
329
+ });
330
+ };
331
+
273
332
  const getFileInstance = async ({ id, uuid }) => {
274
333
  return detail({ id, uuid });
275
334
  };
@@ -283,8 +342,11 @@ module.exports = fp(async (fastify, options) => {
283
342
  deleteFiles,
284
343
  renameFile,
285
344
  getFileBlob,
286
- getFileStream, // 兼容之前api,后面可能会删掉
287
- getFileInstance,
345
+ getFileStream,
346
+ getFileReadStream,
347
+ getCompressFileStream,
348
+ getCompressFileBlob,
349
+ getFileInstance, // 兼容之前api,后面可能会删掉
288
350
  fileRecord: {
289
351
  uploadToFileSystem,
290
352
  uploadFromUrl,
@@ -295,6 +357,9 @@ module.exports = fp(async (fastify, options) => {
295
357
  renameFile,
296
358
  getFileBlob,
297
359
  getFileStream,
360
+ getFileReadStream,
361
+ getCompressFileStream,
362
+ getCompressFileBlob,
298
363
  getFileInstance
299
364
  }
300
365
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kne/fastify-file-manager",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "description": "用于管理静态文件上传查看等",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -49,6 +49,7 @@
49
49
  "dependencies": {
50
50
  "@fastify/multipart": "^9.0.3",
51
51
  "@fastify/static": "^8.1.1",
52
+ "compressing": "^2.0.0",
52
53
  "fs-extra": "^11.2.0",
53
54
  "http-errors": "^2.0.0"
54
55
  }