@kne/fastify-file-manager 0.1.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/README.md ADDED
@@ -0,0 +1,27 @@
1
+
2
+ # fastify-file-manager
3
+
4
+
5
+ ### 描述
6
+
7
+ 用于管理静态文件上传查看等
8
+
9
+
10
+ ### 安装
11
+
12
+ ```shell
13
+ npm i --save @kne/fastify-file-manager
14
+ ```
15
+
16
+ ### 示例
17
+
18
+ #### 示例代码
19
+
20
+
21
+
22
+ ### API
23
+
24
+ | 属性名 | 说明 | 类型 | 默认值 |
25
+ |-----|----|----|-----|
26
+ | | | | |
27
+
package/index.js ADDED
@@ -0,0 +1,43 @@
1
+ const fp = require('fastify-plugin');
2
+ const autoload = require('@fastify/autoload');
3
+ const path = require('path');
4
+ const fs = require('fs-extra');
5
+
6
+ module.exports = fp(
7
+ async (fastify, options) => {
8
+ options = Object.assign(
9
+ {
10
+ root: path.join(process.cwd(), 'static'),
11
+ namespace: 'default',
12
+ prefix: '/static',
13
+ multipart: {},
14
+ static: {},
15
+ authenticateFileRead: async () => {},
16
+ authenticateFileMange: async () => {},
17
+ authenticateFileUpload: async () => {}
18
+ },
19
+ options
20
+ );
21
+ await fs.ensureDir(options.root);
22
+ await fastify.sequelize.addModels(path.resolve(__dirname, './models'));
23
+
24
+ fastify.register(require('@fastify/multipart'), options.multipart);
25
+ fastify.register(autoload, {
26
+ dir: path.resolve(__dirname, './libs'),
27
+ options
28
+ });
29
+ fastify.register(
30
+ require('@fastify/static'),
31
+ Object.assign({}, options.static, {
32
+ root: options.root,
33
+ prefix: options.prefix + '/file/',
34
+ index: false,
35
+ list: false
36
+ })
37
+ );
38
+ },
39
+ {
40
+ name: 'fastify-file-manager',
41
+ dependencies: ['fastify-sequelize']
42
+ }
43
+ );
package/libs/.gitkeep ADDED
File without changes
@@ -0,0 +1,117 @@
1
+ const fp = require('fastify-plugin');
2
+
3
+ module.exports = fp(async (fastify, options) => {
4
+ fastify.post(
5
+ `${options.prefix}/upload`,
6
+ {
7
+ onRequest: [options.authenticateFileUpload]
8
+ },
9
+ async request => {
10
+ const file = await request.file();
11
+ if (!file) {
12
+ throw new Error('不能获取到上传文件');
13
+ }
14
+ //1. 保存到服务器目录 2.对接oss
15
+ return await fastify.fileManagerServices.uploadToFileSystem({ file, namespace: options.namespace });
16
+ }
17
+ );
18
+
19
+ fastify.get(
20
+ `${options.prefix}/file-url/:id`,
21
+ {
22
+ onRequest: [options.authenticateFileRead],
23
+ schema: {
24
+ params: {
25
+ type: 'object',
26
+ required: ['id'],
27
+ properties: {
28
+ id: { type: 'string' }
29
+ }
30
+ }
31
+ }
32
+ },
33
+ async request => {
34
+ const { id } = request.params;
35
+ return await fastify.fileManagerServices.getFileUrl({ id, namespace: options.namespace });
36
+ }
37
+ );
38
+
39
+ fastify.get(
40
+ `${options.prefix}/file-id/:id`,
41
+ {
42
+ onRequest: [options.authenticateFileRead],
43
+ schema: {
44
+ query: {
45
+ type: 'object',
46
+ properties: {
47
+ attachment: { type: 'boolean' },
48
+ filename: { type: 'string' }
49
+ }
50
+ },
51
+ params: {
52
+ type: 'object',
53
+ required: ['id'],
54
+ properties: {
55
+ id: { type: 'string' }
56
+ }
57
+ }
58
+ }
59
+ },
60
+ async (request, reply) => {
61
+ const { id } = request.params;
62
+ const { attachment, filename: targetFilename } = request.query;
63
+ const { targetFileName, filename } = await fastify.fileManagerServices.getFileInfo({
64
+ id,
65
+ namespace: options.namespace
66
+ });
67
+ return attachment ? reply.download(targetFileName, targetFilename || filename) : reply.sendFile(targetFileName);
68
+ }
69
+ );
70
+
71
+ fastify.get(
72
+ `${options.prefix}/file-list`,
73
+ {
74
+ onRequest: [options.authenticateFileMange],
75
+ schema: {
76
+ query: {}
77
+ }
78
+ },
79
+ async request => {
80
+ const { filter, perPage, currentPage } = Object.assign({}, request.query, {
81
+ perPage: 20,
82
+ currentPage: 1
83
+ });
84
+ return await fastify.fileManagerServices.getFileList({
85
+ filter,
86
+ namespace: options.namespace,
87
+ perPage,
88
+ currentPage
89
+ });
90
+ }
91
+ );
92
+
93
+ fastify.post(
94
+ `${options.prefix}/delete-file`,
95
+ {
96
+ onRequest: [options.authenticateFileMange],
97
+ schema: {
98
+ body: {
99
+ type: 'object',
100
+ required: ['id'],
101
+ properties: {
102
+ id: { type: 'string' }
103
+ }
104
+ }
105
+ }
106
+ },
107
+ async request => {
108
+ const { id } = request.body;
109
+ await fastify.fileManagerServices.deleteFile({ id, namespace: options.namespace });
110
+ return {};
111
+ }
112
+ );
113
+
114
+ fastify.get(`${options.prefix}`, async () => {
115
+ return 'living';
116
+ });
117
+ });
@@ -0,0 +1,83 @@
1
+ const fp = require('fastify-plugin');
2
+ const fs = require('fs-extra');
3
+ const crypto = require('crypto');
4
+ const path = require('path');
5
+
6
+ module.exports = fp(async (fastify, options) => {
7
+ const uploadToFileSystem = async ({ file, namespace }) => {
8
+ const { filename, encoding, mimetype } = file;
9
+ const buffer = await file.toBuffer();
10
+ const hash = crypto.createHash('md5');
11
+ hash.update(buffer);
12
+ const digest = hash.digest('hex');
13
+ const extension = path.extname(filename);
14
+ const filepath = path.resolve(options.root, `${digest}${extension}`);
15
+ await fs.writeFile(filepath, buffer);
16
+ console.log({
17
+ filename,
18
+ namespace,
19
+ encoding,
20
+ mimetype,
21
+ hash: digest,
22
+ size: buffer.byteLength
23
+ });
24
+ return await fastify.models.fileManager.create({
25
+ filename,
26
+ namespace,
27
+ encoding,
28
+ mimetype,
29
+ hash: digest,
30
+ size: buffer.byteLength
31
+ });
32
+ };
33
+
34
+ const getFileUrl = async ({ id, namespace }) => {
35
+ const file = await fastify.models.fileManager.findByPk(id, {
36
+ where: { namespace }
37
+ });
38
+ if (!file) {
39
+ throw new Error('文件不存在');
40
+ }
41
+ const extension = path.extname(file.filename);
42
+ return `${options.prefix}/file/${file.hash}${extension}?filename=${file.filename}`;
43
+ };
44
+
45
+ const getFileInfo = async ({ id, namespace }) => {
46
+ const file = await fastify.models.fileManager.findByPk(id, {
47
+ where: { namespace }
48
+ });
49
+ if (!file) {
50
+ throw new Error('文件不存在');
51
+ }
52
+ const extension = path.extname(file.filename);
53
+ return Object.assign({}, file, {
54
+ targetFileName: `${file.hash}${extension}`
55
+ });
56
+ };
57
+
58
+ const getFileList = async ({ filter, namespace, currentPage, perPage }) => {
59
+ const queryFilter = { namespace };
60
+ const { count, rows } = await fastify.models.fileManager.findAndCountAll({
61
+ where: queryFilter,
62
+ offset: currentPage * (currentPage - 1),
63
+ limit: perPage
64
+ });
65
+ return {
66
+ pageData: rows,
67
+ totalCount: count
68
+ };
69
+ };
70
+
71
+ const deleteFile = async ({ id, namespace }) => {
72
+ const file = await fastify.models.fileManager.findByPk(id, {
73
+ where: { namespace }
74
+ });
75
+ if (!file) {
76
+ throw new Error('文件不存在');
77
+ }
78
+
79
+ await file.destroy();
80
+ };
81
+
82
+ fastify.decorate('fileManagerServices', { uploadToFileSystem, getFileUrl, getFileInfo, getFileList, deleteFile });
83
+ });
@@ -0,0 +1,23 @@
1
+ module.exports = (sequelize, DataTypes) => {
2
+ return sequelize.define('fileManager', {
3
+ id: {
4
+ type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true
5
+ }, filename: {
6
+ type: DataTypes.STRING, allowNull: false
7
+ }, hash: {
8
+ type: DataTypes.STRING, allowNull: false
9
+ }, namespace: {
10
+ type: DataTypes.STRING, defaultValue: 'default'
11
+ }, size: {
12
+ type: DataTypes.INTEGER, allowNull: false
13
+ }, encoding: DataTypes.STRING, mimetype: DataTypes.STRING
14
+ }, {
15
+ indexes: [{
16
+ fields: ['namespace']
17
+ }, {
18
+ fields: ['filename']
19
+ }, {
20
+ fields: ['hash']
21
+ }]
22
+ });
23
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@kne/fastify-file-manager",
3
+ "version": "0.1.0",
4
+ "description": "用于管理静态文件上传查看等",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "init": "husky",
8
+ "build:md": "npx @kne/md-doc",
9
+ "start:md": "npx @kne/md-doc --watch",
10
+ "prettier": "prettier --config .prettierrc --write '{libs/**/*,index}.{js,jsx,ts,tsx,json,css,scss}'",
11
+ "lint-staged": "npx lint-staged"
12
+ },
13
+ "lint-staged": {
14
+ "{libs/**/*,index}.{js,jsx,ts,tsx,json,css,scss}": [
15
+ "prettier --config .prettierrc --write",
16
+ "git add"
17
+ ]
18
+ },
19
+ "files": [
20
+ "index.js",
21
+ "libs",
22
+ "models"
23
+ ],
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/kne-union/fastify-file-manager.git"
27
+ },
28
+ "keywords": [],
29
+ "author": "linzp",
30
+ "license": "ISC",
31
+ "bugs": {
32
+ "url": "https://github.com/kne-union/fastify-file-manager/issues"
33
+ },
34
+ "homepage": "https://github.com/kne-union/fastify-file-manager#readme",
35
+ "devDependencies": {
36
+ "@kne/fastify-sequelize": "^0.1.3",
37
+ "fastify": "^4.27.0",
38
+ "husky": "^9.0.11",
39
+ "prettier": "^3.2.5",
40
+ "sqlite3": "^5.1.7"
41
+ },
42
+ "dependencies": {
43
+ "@fastify/autoload": "^5.8.2",
44
+ "@fastify/multipart": "^8.2.0",
45
+ "@fastify/static": "^7.0.4",
46
+ "fastify-plugin": "^4.5.1",
47
+ "fs-extra": "^11.2.0"
48
+ }
49
+ }