@kne/fastify-file-manager 1.1.1 → 1.1.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.
package/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const fp = require('fastify-plugin');
2
2
  const path = require('path');
3
3
  const fs = require('fs-extra');
4
+ const packageJson = require('./package.json');
4
5
 
5
6
  module.exports = fp(
6
7
  async (fastify, options) => {
@@ -8,12 +9,13 @@ module.exports = fp(
8
9
  {
9
10
  root: path.join(process.cwd(), 'static'),
10
11
  namespace: 'default',
11
- prefix: '/api/static',
12
+ prefix: `/api/v${packageJson.version.split('.')[0]}/static`,
13
+ dbTableNamePrefix: 't_file_manager_',
12
14
  multipart: {},
13
15
  static: {},
14
16
  authenticateFileRead: async () => {},
15
17
  authenticateFileMange: async () => {},
16
- authenticateFileUpload: async () => {}
18
+ authenticateFileWrite: async () => {}
17
19
  },
18
20
  options
19
21
  );
@@ -26,7 +28,7 @@ module.exports = fp(
26
28
  [
27
29
  'models',
28
30
  await fastify.sequelize.addModels(path.resolve(__dirname, './libs/models'), {
29
- prefix: 't_file_manager_'
31
+ prefix: options.dbTableNamePrefix
30
32
  })
31
33
  ],
32
34
  ['services', path.resolve(__dirname, './libs/services')],
@@ -5,7 +5,15 @@ module.exports = fp(async (fastify, options) => {
5
5
  fastify.post(
6
6
  `${options.prefix}/upload`,
7
7
  {
8
- onRequest: [options.authenticateFileUpload]
8
+ onRequest: [options.authenticateFileWrite],
9
+ schema: {
10
+ query: {
11
+ type: 'object',
12
+ properties: {
13
+ namespace: { type: 'string' }
14
+ }
15
+ }
16
+ }
9
17
  },
10
18
  async request => {
11
19
  const file = await request.file();
@@ -13,7 +21,10 @@ module.exports = fp(async (fastify, options) => {
13
21
  throw new Error('不能获取到上传文件');
14
22
  }
15
23
  //1. 保存到服务器目录 2.对接oss
16
- return await services.fileRecord.uploadToFileSystem({ file, namespace: options.namespace });
24
+ return await services.fileRecord.uploadToFileSystem({
25
+ file,
26
+ namespace: request.query.namespace || options.namespace
27
+ });
17
28
  }
18
29
  );
19
30
 
@@ -33,7 +44,7 @@ module.exports = fp(async (fastify, options) => {
33
44
  },
34
45
  async request => {
35
46
  const { id } = request.params;
36
- return await services.fileRecord.getFileUrl({ id, namespace: options.namespace });
47
+ return await services.fileRecord.getFileUrl({ id });
37
48
  }
38
49
  );
39
50
 
@@ -62,57 +73,109 @@ module.exports = fp(async (fastify, options) => {
62
73
  const { id } = request.params;
63
74
  const { attachment, filename: targetFilename } = request.query;
64
75
  const { targetFileName, filename } = await services.fileRecord.getFileInfo({
65
- id,
66
- namespace: options.namespace
76
+ id
67
77
  });
68
78
  return attachment ? reply.download(targetFileName, targetFilename || filename) : reply.sendFile(targetFileName);
69
79
  }
70
80
  );
71
81
 
72
- fastify.get(
82
+ fastify.post(
73
83
  `${options.prefix}/file-list`,
74
84
  {
75
85
  onRequest: [options.authenticateFileMange],
76
86
  schema: {
77
- query: {}
87
+ body: {
88
+ type: 'object',
89
+ properties: {
90
+ perPage: { type: 'number' },
91
+ currentPage: { type: 'number' },
92
+ filter: {
93
+ type: 'object',
94
+ properties: {
95
+ namespace: { type: 'string' },
96
+ size: { type: 'array', items: { type: 'number' } },
97
+ filename: { type: 'string' }
98
+ }
99
+ }
100
+ }
101
+ }
78
102
  }
79
103
  },
80
104
  async request => {
81
- const { filter, perPage, currentPage } = Object.assign({}, request.query, {
82
- perPage: 20,
83
- currentPage: 1
84
- });
105
+ const { filter, perPage, currentPage } = Object.assign(
106
+ {},
107
+ {
108
+ perPage: 20,
109
+ currentPage: 1
110
+ },
111
+ request.body
112
+ );
85
113
  return await services.fileRecord.getFileList({
86
114
  filter,
87
- namespace: options.namespace,
88
115
  perPage,
89
116
  currentPage
90
117
  });
91
118
  }
92
119
  );
93
120
 
121
+ // Replace file
122
+
123
+ fastify.post(
124
+ `${options.prefix}/replace-file`,
125
+ {
126
+ onRequest: [options.authenticateFileMange],
127
+ schema: {
128
+ type: 'object',
129
+ properties: {
130
+ id: { type: 'string' }
131
+ }
132
+ }
133
+ },
134
+ async request => {
135
+ const file = await request.file();
136
+ if (!file) {
137
+ throw new Error('不能获取到上传文件');
138
+ }
139
+ return await services.fileRecord.uploadToFileSystem({ id: request.query.id, file });
140
+ }
141
+ );
142
+
143
+ fastify.post(
144
+ `${options.prefix}/rename-file`,
145
+ {
146
+ onRequest: [options.authenticateFileMange],
147
+ schema: {
148
+ type: 'object',
149
+ properties: {
150
+ id: { type: 'string' },
151
+ filename: { type: 'string' }
152
+ }
153
+ }
154
+ },
155
+ async request => {
156
+ await services.fileRecord.renameFile(request.body);
157
+ return {};
158
+ }
159
+ );
160
+
94
161
  fastify.post(
95
- `${options.prefix}/delete-file`,
162
+ `${options.prefix}/delete-files`,
96
163
  {
97
164
  onRequest: [options.authenticateFileMange],
98
165
  schema: {
99
166
  body: {
100
167
  type: 'object',
101
- required: ['id'],
168
+ required: ['ids'],
102
169
  properties: {
103
- id: { type: 'string' }
170
+ ids: { type: 'array', items: { type: 'string' } }
104
171
  }
105
172
  }
106
173
  }
107
174
  },
108
175
  async request => {
109
- const { id } = request.body;
110
- await services.fileRecord.deleteFile({ id, namespace: options.namespace });
176
+ const { ids } = request.body;
177
+ await services.fileRecord.deleteFiles({ ids });
111
178
  return {};
112
179
  }
113
180
  );
114
-
115
- fastify.get(`${options.prefix}`, async () => {
116
- return 'living';
117
- });
118
181
  });
@@ -5,7 +5,8 @@ const path = require('path');
5
5
 
6
6
  module.exports = fp(async (fastify, options) => {
7
7
  const { models, services } = fastify.fileManager;
8
- const uploadToFileSystem = async ({ file, namespace }) => {
8
+ const { Op } = fastify.sequelize.Sequelize;
9
+ const uploadToFileSystem = async ({ id, file, namespace }) => {
9
10
  const { filename, encoding, mimetype } = file;
10
11
  const buffer = await file.toBuffer();
11
12
  const hash = crypto.createHash('md5');
@@ -14,20 +15,38 @@ module.exports = fp(async (fastify, options) => {
14
15
  const extension = path.extname(filename);
15
16
  const filepath = path.resolve(options.root, `${digest}${extension}`);
16
17
  await fs.writeFile(filepath, buffer);
17
- const outputFile = await models.fileRecord.create({
18
- filename,
19
- namespace: namespace || options.namespace,
20
- encoding,
21
- mimetype,
22
- hash: digest,
23
- size: buffer.byteLength
24
- });
18
+
19
+ const outputFile = await (async create => {
20
+ if (!id) {
21
+ return await create();
22
+ }
23
+ const file = await models.fileRecord.findOne({ where: { uuid: id } });
24
+ if (!file) {
25
+ throw new Error('原文件不存在');
26
+ }
27
+ file.filename = filename;
28
+ file.encoding = encoding;
29
+ file.mimetype = mimetype;
30
+ file.hash = digest;
31
+ file.size = buffer.byteLength;
32
+ await file.save();
33
+ return file;
34
+ })(() =>
35
+ models.fileRecord.create({
36
+ filename,
37
+ namespace: namespace || options.namespace,
38
+ encoding,
39
+ mimetype,
40
+ hash: digest,
41
+ size: buffer.byteLength
42
+ })
43
+ );
25
44
  return Object.assign({}, outputFile.get({ plain: true }), { id: outputFile.uuid });
26
45
  };
27
46
 
28
47
  const getFileUrl = async ({ id, namespace }) => {
29
48
  const file = await models.fileRecord.findOne({
30
- where: { uuid: id, namespace: namespace || options.namespace }
49
+ where: { uuid: id }
31
50
  });
32
51
  if (!file) {
33
52
  throw new Error('文件不存在');
@@ -36,9 +55,9 @@ module.exports = fp(async (fastify, options) => {
36
55
  return `${options.prefix}/file/${file.hash}${extension}?filename=${file.filename}`;
37
56
  };
38
57
 
39
- const getFileInfo = async ({ id, namespace }) => {
58
+ const getFileInfo = async ({ id }) => {
40
59
  const file = await models.fileRecord.findOne({
41
- where: { uuid: id, namespace: namespace || options.namespace }
60
+ where: { uuid: id }
42
61
  });
43
62
  if (!file) {
44
63
  throw new Error('文件不存在');
@@ -50,11 +69,33 @@ module.exports = fp(async (fastify, options) => {
50
69
  });
51
70
  };
52
71
 
53
- const getFileList = async ({ filter, namespace, currentPage, perPage }) => {
54
- const queryFilter = { namespace: namespace || options.namespace };
72
+ const getFileList = async ({ filter, currentPage, perPage }) => {
73
+ // namespace: namespace || options.namespace
74
+ const queryFilter = {};
75
+
76
+ if (filter?.filename) {
77
+ queryFilter.filename = {
78
+ [Op.like]: `%${filter.filename}%`
79
+ };
80
+ }
81
+ if (filter?.size && filter.size.length > 0) {
82
+ queryFilter.size = {};
83
+ if (filter.size[0]) {
84
+ queryFilter.size[Op.gt] = filter.size[0] * 1024;
85
+ }
86
+ if (filter.size[1]) {
87
+ queryFilter.size[Op.lt] = filter.size[1] * 1024;
88
+ }
89
+ }
90
+ if (filter?.namespace) {
91
+ queryFilter.namespace = {
92
+ [Op.like]: `%${filter.namespace}%`
93
+ };
94
+ }
95
+
55
96
  const { count, rows } = await models.fileRecord.findAndCountAll({
56
97
  where: queryFilter,
57
- offset: currentPage * (currentPage - 1),
98
+ offset: perPage * (currentPage - 1),
58
99
  limit: perPage
59
100
  });
60
101
  return {
@@ -63,15 +104,26 @@ module.exports = fp(async (fastify, options) => {
63
104
  };
64
105
  };
65
106
 
66
- const deleteFile = async ({ id, namespace }) => {
107
+ const deleteFiles = async ({ ids }) => {
108
+ await models.fileRecord.destroy({
109
+ where: {
110
+ uuid: {
111
+ [Op.in]: ids
112
+ }
113
+ }
114
+ });
115
+ };
116
+
117
+ const renameFile = async ({ id, filename }) => {
67
118
  const file = await models.fileRecord.findOne({
68
- where: { uuid: id, namespace: namespace || options.namespace }
119
+ where: { uuid: id }
69
120
  });
70
121
  if (!file) {
71
122
  throw new Error('文件不存在');
72
123
  }
73
-
74
- await file.destroy();
124
+ file.filename = filename;
125
+ await file.save();
75
126
  };
76
- services.fileRecord = { uploadToFileSystem, getFileUrl, getFileInfo, getFileList, deleteFile };
127
+
128
+ services.fileRecord = { uploadToFileSystem, getFileUrl, getFileInfo, getFileList, deleteFiles, renameFile };
77
129
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kne/fastify-file-manager",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "用于管理静态文件上传查看等",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -36,6 +36,7 @@
36
36
  "fastify": "^4.27.0",
37
37
  "husky": "^9.0.11",
38
38
  "prettier": "^3.2.5",
39
+ "qs": "^6.12.3",
39
40
  "sqlite3": "^5.1.7"
40
41
  },
41
42
  "dependencies": {