@kne/fastify-file-manager 2.0.0-alpha.0 → 2.0.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.
- package/index.js +2 -1
- package/libs/controllers/index.js +124 -110
- package/libs/services/file-record.js +183 -144
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const fp = require('fastify-plugin');
|
|
2
|
-
const path = require('path');
|
|
2
|
+
const path = require('node:path');
|
|
3
3
|
const fs = require('fs-extra');
|
|
4
4
|
const packageJson = require('./package.json');
|
|
5
5
|
|
|
@@ -31,6 +31,7 @@ module.exports = fp(
|
|
|
31
31
|
fastify.register(require('@kne/fastify-namespace'), {
|
|
32
32
|
name: 'fileManager',
|
|
33
33
|
options,
|
|
34
|
+
singleton: true,
|
|
34
35
|
modules: [
|
|
35
36
|
[
|
|
36
37
|
'models',
|
|
@@ -1,134 +1,148 @@
|
|
|
1
1
|
const fp = require('fastify-plugin');
|
|
2
2
|
|
|
3
3
|
module.exports = fp(async (fastify, options) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}, async request => {
|
|
14
|
-
const file = await request.file();
|
|
15
|
-
if (!file) {
|
|
16
|
-
throw new Error('不能获取到上传文件');
|
|
4
|
+
const { services } = fastify.fileManager;
|
|
5
|
+
fastify.post(`${options.prefix}/upload`, {
|
|
6
|
+
onRequest: options.createAuthenticate('file:write'), schema: {
|
|
7
|
+
summary: '上传文件', description: '上传单个文件到服务器或配置的存储服务', query: {
|
|
8
|
+
type: 'object', properties: {
|
|
9
|
+
namespace: { type: 'string', description: '文件分类命名空间' }
|
|
17
10
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}, async request => {
|
|
14
|
+
const file = await request.file();
|
|
15
|
+
if (!file) {
|
|
16
|
+
throw new Error('不能获取到上传文件');
|
|
17
|
+
}
|
|
18
|
+
return await services.fileRecord.uploadToFileSystem({
|
|
19
|
+
file, namespace: request.query.namespace || options.namespace
|
|
22
20
|
});
|
|
21
|
+
});
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
23
|
+
fastify.post(`${options.prefix}/uploadUrl`, {
|
|
24
|
+
onRequest: options.createAuthenticate('file:write'), schema: {
|
|
25
|
+
summary: '上传URL文件', description: '上传单个文件到服务器或配置的存储服务', body: {
|
|
26
|
+
type: 'object', properties: {
|
|
27
|
+
url: { type: 'string', description: '文件url' },
|
|
28
|
+
namespace: { type: 'string', description: '文件分类命名空间' }
|
|
31
29
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}, async request => {
|
|
33
|
+
return await services.fileRecord.uploadFromUrl({
|
|
34
|
+
url: request.body.url, namespace: request.body.namespace || options.namespace
|
|
35
35
|
});
|
|
36
|
+
});
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
filename: {type: 'string', description: '下载文件名'}
|
|
43
|
-
}
|
|
44
|
-
}, params: {
|
|
45
|
-
type: 'object', required: ['id'], properties: {
|
|
46
|
-
id: {type: 'string', description: '文件id'}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
38
|
+
fastify.get(`${options.prefix}/file-url/:id`, {
|
|
39
|
+
onRequest: options.createAuthenticate('file:read'), schema: {
|
|
40
|
+
summary: '获取文件url', description: '获取文件url', params: {
|
|
41
|
+
type: 'object', required: ['id'], properties: {
|
|
42
|
+
id: { type: 'string', description: '文件id' }
|
|
49
43
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}, async request => {
|
|
47
|
+
const { id } = request.params;
|
|
48
|
+
return await services.fileRecord.getFileUrl({ id });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
fastify.get(`${options.prefix}/file-id/:id`, {
|
|
52
|
+
onRequest: options.createAuthenticate('file:read'), schema: {
|
|
53
|
+
summary: '获取文件信息', description: '获取文件信息', query: {
|
|
54
|
+
type: 'object', properties: {
|
|
55
|
+
attachment: { type: 'boolean', description: '是否下载' },
|
|
56
|
+
filename: { type: 'string', description: '下载文件名' }
|
|
57
|
+
}
|
|
58
|
+
}, params: {
|
|
59
|
+
type: 'object', required: ['id'], properties: {
|
|
60
|
+
id: { type: 'string', description: '文件id' }
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}, async (request, reply) => {
|
|
65
|
+
const { id } = request.params;
|
|
66
|
+
const { attachment, filename: targetFilename } = request.query;
|
|
67
|
+
const { filePath, targetFile, filename, mimetype, ...props } = await services.fileRecord.getFileInfo({
|
|
68
|
+
id
|
|
63
69
|
});
|
|
70
|
+
if (targetFile) {
|
|
71
|
+
const outputFilename = encodeURIComponent(targetFilename || filename);
|
|
72
|
+
reply.header('Content-Type', mimetype);
|
|
73
|
+
reply.header('Content-Disposition', attachment ? `attachment; filename="${outputFilename}"` : `filename="${outputFilename}"`);
|
|
74
|
+
return reply.send(targetFile);
|
|
75
|
+
}
|
|
76
|
+
return attachment ? reply.download(filePath, targetFilename || filename) : reply.sendFile(filePath);
|
|
77
|
+
});
|
|
64
78
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
+
fastify.post(`${options.prefix}/file-list`, {
|
|
80
|
+
onRequest: options.createAuthenticate('file:mange'), schema: {
|
|
81
|
+
summary: '获取文件列表', description: '查询指定命名空间下的文件列表', body: {
|
|
82
|
+
type: 'object', properties: {
|
|
83
|
+
perPage: { type: 'number', description: '每页数量' },
|
|
84
|
+
currentPage: { type: 'number', description: '当前页数' },
|
|
85
|
+
filter: {
|
|
86
|
+
type: 'object', properties: {
|
|
87
|
+
namespace: { type: 'string', description: '文件分类命名空间' },
|
|
88
|
+
size: { type: 'array', items: { type: 'number' }, description: '文件大小' },
|
|
89
|
+
filename: { type: 'string', description: '文件名' }
|
|
79
90
|
}
|
|
91
|
+
}
|
|
80
92
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}, async request => {
|
|
96
|
+
const { filter, perPage, currentPage } = Object.assign({}, {
|
|
97
|
+
perPage: 20, currentPage: 1
|
|
98
|
+
}, request.body);
|
|
99
|
+
return await services.fileRecord.getFileList({
|
|
100
|
+
filter, perPage, currentPage
|
|
88
101
|
});
|
|
102
|
+
});
|
|
89
103
|
|
|
90
|
-
|
|
104
|
+
// Replace file
|
|
91
105
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
}
|
|
106
|
+
fastify.post(`${options.prefix}/replace-file`, {
|
|
107
|
+
onRequest: options.createAuthenticate('file:mange'), schema: {
|
|
108
|
+
summary: '替换文件', description: '替换文件', query: {
|
|
109
|
+
type: 'object', properties: {
|
|
110
|
+
id: { type: 'string', description: '文件id' }
|
|
99
111
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}, async request => {
|
|
115
|
+
const file = await request.file();
|
|
116
|
+
if (!file) {
|
|
117
|
+
throw new Error('不能获取到上传文件');
|
|
118
|
+
}
|
|
119
|
+
return await services.fileRecord.uploadToFileSystem({ id: request.query.id, file });
|
|
120
|
+
});
|
|
107
121
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
}
|
|
122
|
+
fastify.post(`${options.prefix}/rename-file`, {
|
|
123
|
+
onRequest: options.createAuthenticate('file:mange'), schema: {
|
|
124
|
+
summary: '重命名文件', description: '重命名文件', body: {
|
|
125
|
+
type: 'object', properties: {
|
|
126
|
+
id: { type: 'string', description: '文件id' }, filename: { type: 'string', description: '新文件名' }
|
|
115
127
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}, async request => {
|
|
131
|
+
await services.fileRecord.renameFile(request.body);
|
|
132
|
+
return {};
|
|
133
|
+
});
|
|
120
134
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
}
|
|
135
|
+
fastify.post(`${options.prefix}/delete-files`, {
|
|
136
|
+
onRequest: options.createAuthenticate('file:mange'), schema: {
|
|
137
|
+
summary: '删除文件', description: '删除文件', body: {
|
|
138
|
+
type: 'object', required: ['ids'], properties: {
|
|
139
|
+
ids: { type: 'array', items: { type: 'string' }, description: '文件id列表' }
|
|
128
140
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}, async request => {
|
|
144
|
+
const { ids } = request.body;
|
|
145
|
+
await services.fileRecord.deleteFiles({ ids });
|
|
146
|
+
return {};
|
|
147
|
+
});
|
|
134
148
|
});
|
|
@@ -2,165 +2,204 @@ const fp = require('fastify-plugin');
|
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const {NotFound} = require('http-errors');
|
|
5
|
+
const { NotFound } = require('http-errors');
|
|
6
6
|
|
|
7
7
|
module.exports = fp(async (fastify, options) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const digest = hash.digest('hex');
|
|
16
|
-
const extension = path.extname(filename);
|
|
8
|
+
const { models, services } = fastify.fileManager;
|
|
9
|
+
const { Op } = fastify.sequelize.Sequelize;
|
|
10
|
+
const uploadToFileSystem = async ({ id, file, namespace }) => {
|
|
11
|
+
const { filename, encoding, mimetype } = file;
|
|
12
|
+
const hash = crypto.createHash('md5');
|
|
13
|
+
const extension = path.extname(filename);
|
|
14
|
+
let buffer = Buffer.alloc(0);
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
await fs.writeFile(filepath, buffer);
|
|
26
|
-
storageType = 'local';
|
|
27
|
-
}
|
|
16
|
+
// 使用流处理文件数据
|
|
17
|
+
const stream = file.createReadStream();
|
|
18
|
+
for await (const chunk of stream) {
|
|
19
|
+
hash.update(chunk);
|
|
20
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
21
|
+
}
|
|
22
|
+
const digest = hash.digest('hex');
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
namespace: namespace || options.namespace,
|
|
49
|
-
encoding,
|
|
50
|
-
mimetype,
|
|
51
|
-
hash: digest,
|
|
52
|
-
size: buffer.byteLength,
|
|
53
|
-
storageType
|
|
54
|
-
})
|
|
55
|
-
);
|
|
56
|
-
return Object.assign({}, outputFile.get({plain: true}), {id: outputFile.uuid});
|
|
57
|
-
};
|
|
24
|
+
let storageType;
|
|
25
|
+
const ossServices = options.ossAdapter();
|
|
26
|
+
if (typeof ossServices.uploadFile === 'function') {
|
|
27
|
+
// 使用流上传到OSS
|
|
28
|
+
const uploadStream = file.createReadStream();
|
|
29
|
+
await ossServices.uploadFileStream({ stream: uploadStream, filename: `${digest}${extension}` });
|
|
30
|
+
storageType = 'oss';
|
|
31
|
+
} else {
|
|
32
|
+
// 使用流写入本地文件
|
|
33
|
+
const filepath = path.resolve(options.root, `${digest}${extension}`);
|
|
34
|
+
const writeStream = fs.createWriteStream(filepath);
|
|
35
|
+
const readStream = file.createReadStream();
|
|
36
|
+
await new Promise((resolve, reject) => {
|
|
37
|
+
readStream.pipe(writeStream)
|
|
38
|
+
.on('finish', resolve)
|
|
39
|
+
.on('error', reject);
|
|
40
|
+
});
|
|
41
|
+
storageType = 'local';
|
|
42
|
+
}
|
|
58
43
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
44
|
+
const outputFile = await (async create => {
|
|
45
|
+
if (!id) {
|
|
46
|
+
return await create();
|
|
47
|
+
}
|
|
48
|
+
const file = await models.fileRecord.findOne({ where: { uuid: id } });
|
|
49
|
+
if (!file) {
|
|
50
|
+
throw new Error('原文件不存在');
|
|
51
|
+
}
|
|
52
|
+
file.filename = filename;
|
|
53
|
+
file.encoding = encoding;
|
|
54
|
+
file.mimetype = mimetype;
|
|
55
|
+
file.hash = digest;
|
|
56
|
+
file.size = buffer.byteLength;
|
|
57
|
+
file.storageType = storageType;
|
|
58
|
+
await file.save();
|
|
59
|
+
return file;
|
|
60
|
+
})(() =>
|
|
61
|
+
models.fileRecord.create({
|
|
62
|
+
filename,
|
|
63
|
+
namespace: namespace || options.namespace,
|
|
64
|
+
encoding,
|
|
65
|
+
mimetype,
|
|
66
|
+
hash: digest,
|
|
67
|
+
size: buffer.byteLength,
|
|
68
|
+
storageType
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
return Object.assign({}, outputFile.get({ plain: true }), { id: outputFile.uuid });
|
|
72
|
+
};
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
const uploadFromUrl = async ({ id, url, namespace }) => {
|
|
75
|
+
const response = await fetch(url);
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
throw new Error('下载文件失败');
|
|
78
|
+
}
|
|
79
|
+
const chunks = [];
|
|
80
|
+
for await (const chunk of response.body) {
|
|
81
|
+
chunks.push(chunk);
|
|
82
|
+
}
|
|
83
|
+
const buffer = Buffer.concat(chunks);
|
|
84
|
+
const tempFile = {
|
|
85
|
+
filename: path.basename(url).split('?')[0],
|
|
86
|
+
mimetype: response.headers.get('content-type'),
|
|
87
|
+
encoding: 'binary',
|
|
88
|
+
createReadStream: () => {
|
|
89
|
+
const readable = new require('stream').Readable();
|
|
90
|
+
readable.push(buffer);
|
|
91
|
+
readable.push(null);
|
|
92
|
+
return readable;
|
|
93
|
+
}
|
|
79
94
|
};
|
|
95
|
+
return await uploadToFileSystem({ id, file: tempFile, namespace });
|
|
96
|
+
};
|
|
80
97
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
targetFile = await ossServices.downloadFile({filename: targetFileName});
|
|
97
|
-
}
|
|
98
|
-
return Object.assign({}, file.get({pain: true}), {
|
|
99
|
-
id: file.uuid,
|
|
100
|
-
filePath: targetFileName,
|
|
101
|
-
targetFile
|
|
102
|
-
});
|
|
103
|
-
};
|
|
98
|
+
const getFileUrl = async ({ id, namespace }) => {
|
|
99
|
+
const file = await models.fileRecord.findOne({
|
|
100
|
+
where: { uuid: id }
|
|
101
|
+
});
|
|
102
|
+
if (!file) {
|
|
103
|
+
throw new Error('文件不存在');
|
|
104
|
+
}
|
|
105
|
+
const extension = path.extname(file.filename);
|
|
106
|
+
const ossServices = options.ossAdapter();
|
|
107
|
+
if (file.storageType === 'oss' && typeof ossServices.getFileLink !== 'function') {
|
|
108
|
+
throw new Error('ossAdapter未正确配置无法读取oss类型存储文件');
|
|
109
|
+
}
|
|
110
|
+
if (file.storageType === 'oss') {
|
|
111
|
+
return await ossServices.getFileLink({ filename: `${file.hash}${extension}` });
|
|
112
|
+
}
|
|
104
113
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
114
|
+
if (!(await fs.exists(`${options.root}/${file.hash}${extension}`))) {
|
|
115
|
+
throw new NotFound();
|
|
116
|
+
}
|
|
117
|
+
return `${options.prefix}/file/${file.hash}${extension}?filename=${file.filename}`;
|
|
118
|
+
};
|
|
108
119
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
120
|
+
const getFileInfo = async ({ id }) => {
|
|
121
|
+
const file = await models.fileRecord.findOne({
|
|
122
|
+
where: { uuid: id }
|
|
123
|
+
});
|
|
124
|
+
if (!file) {
|
|
125
|
+
throw new Error('文件不存在');
|
|
126
|
+
}
|
|
127
|
+
const extension = path.extname(file.filename);
|
|
128
|
+
const targetFileName = `${file.hash}${extension}`;
|
|
129
|
+
const ossServices = options.ossAdapter();
|
|
130
|
+
if (file.storageType === 'oss' && typeof ossServices.downloadFile !== 'function') {
|
|
131
|
+
throw new Error('ossAdapter未正确配置无法读取oss类型存储文件');
|
|
132
|
+
}
|
|
133
|
+
let targetFile;
|
|
134
|
+
if (file.storageType === 'oss') {
|
|
135
|
+
targetFile = await ossServices.downloadFile({ filename: targetFileName });
|
|
136
|
+
}
|
|
137
|
+
return Object.assign({}, file.get({ pain: true }), {
|
|
138
|
+
id: file.uuid,
|
|
139
|
+
filePath: targetFileName,
|
|
140
|
+
targetFile
|
|
141
|
+
});
|
|
142
|
+
};
|
|
128
143
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
limit: perPage
|
|
133
|
-
});
|
|
134
|
-
return {
|
|
135
|
-
pageData: rows.map(item => Object.assign({}, item.get({plain: true}), {id: item.uuid})),
|
|
136
|
-
totalCount: count
|
|
137
|
-
};
|
|
138
|
-
};
|
|
144
|
+
const getFileList = async ({ filter, currentPage, perPage }) => {
|
|
145
|
+
// namespace: namespace || options.namespace
|
|
146
|
+
const queryFilter = {};
|
|
139
147
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
+
if (filter?.filename) {
|
|
149
|
+
queryFilter.filename = {
|
|
150
|
+
[Op.like]: `%${filter.filename}%`
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (filter?.size && filter.size.length > 0) {
|
|
154
|
+
queryFilter.size = {};
|
|
155
|
+
if (filter.size[0]) {
|
|
156
|
+
queryFilter.size[Op.gt] = filter.size[0] * 1024;
|
|
157
|
+
}
|
|
158
|
+
if (filter.size[1]) {
|
|
159
|
+
queryFilter.size[Op.lt] = filter.size[1] * 1024;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (filter?.namespace) {
|
|
163
|
+
queryFilter.namespace = {
|
|
164
|
+
[Op.like]: `%${filter.namespace}%`
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const { count, rows } = await models.fileRecord.findAndCountAll({
|
|
169
|
+
where: queryFilter,
|
|
170
|
+
offset: perPage * (currentPage - 1),
|
|
171
|
+
limit: perPage
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
pageData: rows.map(item => Object.assign({}, item.get({ plain: true }), { id: item.uuid })),
|
|
175
|
+
totalCount: count
|
|
148
176
|
};
|
|
177
|
+
};
|
|
149
178
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
throw new Error('文件不存在');
|
|
179
|
+
const deleteFiles = async ({ ids }) => {
|
|
180
|
+
await models.fileRecord.destroy({
|
|
181
|
+
where: {
|
|
182
|
+
uuid: {
|
|
183
|
+
[Op.in]: ids
|
|
156
184
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
};
|
|
160
188
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
fileRecord: {uploadToFileSystem, getFileUrl, getFileInfo, getFileList, deleteFiles, renameFile}
|
|
189
|
+
const renameFile = async ({ id, filename }) => {
|
|
190
|
+
const file = await models.fileRecord.findOne({
|
|
191
|
+
where: { uuid: id }
|
|
165
192
|
});
|
|
193
|
+
if (!file) {
|
|
194
|
+
throw new Error('文件不存在');
|
|
195
|
+
}
|
|
196
|
+
file.filename = filename;
|
|
197
|
+
await file.save();
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
Object.assign(services, {
|
|
201
|
+
uploadToFileSystem, uploadFromUrl, getFileUrl, getFileInfo, getFileList, deleteFiles, renameFile,
|
|
202
|
+
// 兼容之前api,后面可能会删掉
|
|
203
|
+
fileRecord: { uploadToFileSystem, uploadFromUrl, getFileUrl, getFileInfo, getFileList, deleteFiles, renameFile }
|
|
204
|
+
});
|
|
166
205
|
});
|