@nocobase/plugin-file-manager 1.8.0-beta.9 → 1.8.1
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/dist/client/index.js +1 -1
- package/dist/common/collections/attachments.d.ts +1 -0
- package/dist/common/collections/attachments.js +1 -0
- package/dist/externalVersion.js +7 -7
- package/dist/node_modules/@aws-sdk/client-s3/package.json +1 -1
- package/dist/node_modules/mime-match/package.json +1 -1
- package/dist/node_modules/mime-types/LICENSE +23 -0
- package/dist/node_modules/mime-types/index.js +14 -0
- package/dist/node_modules/mime-types/mimeScore.js +52 -0
- package/dist/node_modules/mime-types/package.json +1 -0
- package/dist/node_modules/mkdirp/package.json +1 -1
- package/dist/node_modules/multer-aliyun-oss/package.json +1 -1
- package/dist/node_modules/multer-cos/package.json +1 -1
- package/dist/node_modules/multer-s3/package.json +1 -1
- package/dist/node_modules/url-join/package.json +1 -1
- package/dist/server/actions/attachments.js +104 -12
- package/package.json +8 -2
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// 'mime-score' back-ported to CommonJS
|
|
2
|
+
|
|
3
|
+
// Score RFC facets (see https://tools.ietf.org/html/rfc6838#section-3)
|
|
4
|
+
var FACET_SCORES = {
|
|
5
|
+
'prs.': 100,
|
|
6
|
+
'x-': 200,
|
|
7
|
+
'x.': 300,
|
|
8
|
+
'vnd.': 400,
|
|
9
|
+
default: 900
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Score mime source (Logic originally from `jshttp/mime-types` module)
|
|
13
|
+
var SOURCE_SCORES = {
|
|
14
|
+
nginx: 10,
|
|
15
|
+
apache: 20,
|
|
16
|
+
iana: 40,
|
|
17
|
+
default: 30 // definitions added by `jshttp/mime-db` project?
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
var TYPE_SCORES = {
|
|
21
|
+
// prefer application/xml over text/xml
|
|
22
|
+
// prefer application/rtf over text/rtf
|
|
23
|
+
application: 1,
|
|
24
|
+
|
|
25
|
+
// prefer font/woff over application/font-woff
|
|
26
|
+
font: 2,
|
|
27
|
+
|
|
28
|
+
default: 0
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get each component of the score for a mime type. The sum of these is the
|
|
33
|
+
* total score. The higher the score, the more "official" the type.
|
|
34
|
+
*/
|
|
35
|
+
module.exports = function mimeScore (mimeType, source = 'default') {
|
|
36
|
+
if (mimeType === 'application/octet-stream') {
|
|
37
|
+
return 0
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const [type, subtype] = mimeType.split('/')
|
|
41
|
+
|
|
42
|
+
const facet = subtype.replace(/(\.|x-).*/, '$1')
|
|
43
|
+
|
|
44
|
+
const facetScore = FACET_SCORES[facet] || FACET_SCORES.default
|
|
45
|
+
const sourceScore = SOURCE_SCORES[source] || SOURCE_SCORES.default
|
|
46
|
+
const typeScore = TYPE_SCORES[type] || TYPE_SCORES.default
|
|
47
|
+
|
|
48
|
+
// All else being equal prefer shorter types
|
|
49
|
+
const lengthScore = 1 - mimeType.length / 100
|
|
50
|
+
|
|
51
|
+
return facetScore + sourceScore + typeScore + lengthScore
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"mime-types","description":"The ultimate javascript content-type utility.","version":"3.0.1","contributors":["Douglas Christopher Wilson <doug@somethingdoug.com>","Jeremiah Senkpiel <fishrock123@rocketmail.com> (https://searchbeam.jit.su)","Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"],"license":"MIT","keywords":["mime","types"],"repository":"jshttp/mime-types","dependencies":{"mime-db":"^1.54.0"},"devDependencies":{"eslint":"8.33.0","eslint-config-standard":"14.1.1","eslint-plugin-import":"2.27.5","eslint-plugin-markdown":"3.0.0","eslint-plugin-node":"11.1.0","eslint-plugin-promise":"6.1.1","eslint-plugin-standard":"4.1.0","mocha":"10.2.0","nyc":"15.1.0"},"files":["HISTORY.md","LICENSE","index.js","mimeScore.js"],"engines":{"node":">= 0.6"},"scripts":{"lint":"eslint .","test":"mocha --reporter spec test/test.js","test-ci":"nyc --reporter=lcov --reporter=text npm test","test-cov":"nyc --reporter=html --reporter=text npm test"},"_lastModified":"2025-07-09T08:38:42.224Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"mkdirp","description":"Recursively mkdir, like `mkdir -p`","version":"0.5.6","publishConfig":{"tag":"legacy"},"author":"James Halliday <mail@substack.net> (http://substack.net)","main":"index.js","keywords":["mkdir","directory"],"repository":{"type":"git","url":"https://github.com/substack/node-mkdirp.git"},"scripts":{"test":"tap test/*.js"},"dependencies":{"minimist":"^1.2.6"},"devDependencies":{"tap":"^16.0.1"},"bin":"bin/cmd.js","license":"MIT","files":["bin","index.js"],"_lastModified":"2025-
|
|
1
|
+
{"name":"mkdirp","description":"Recursively mkdir, like `mkdir -p`","version":"0.5.6","publishConfig":{"tag":"legacy"},"author":"James Halliday <mail@substack.net> (http://substack.net)","main":"index.js","keywords":["mkdir","directory"],"repository":{"type":"git","url":"https://github.com/substack/node-mkdirp.git"},"scripts":{"test":"tap test/*.js"},"dependencies":{"minimist":"^1.2.6"},"devDependencies":{"tap":"^16.0.1"},"bin":"bin/cmd.js","license":"MIT","files":["bin","index.js"],"_lastModified":"2025-07-09T08:38:46.490Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"multer-aliyun-oss","version":"2.1.3","description":"Multer Storage for AliYun OSS","main":"index.js","scripts":{},"author":"AngusYoung","license":"ISC","repository":{"type":"git","url":"git+https://github.com/ay86/multer-aliyun-oss.git"},"keywords":["multer","storage","aliyun","oss"],"dependencies":{"ali-oss":"^6.1.0"},"_lastModified":"2025-
|
|
1
|
+
{"name":"multer-aliyun-oss","version":"2.1.3","description":"Multer Storage for AliYun OSS","main":"index.js","scripts":{},"author":"AngusYoung","license":"ISC","repository":{"type":"git","url":"git+https://github.com/ay86/multer-aliyun-oss.git"},"keywords":["multer","storage","aliyun","oss"],"dependencies":{"ali-oss":"^6.1.0"},"_lastModified":"2025-07-09T08:38:46.415Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"_from":"multer-cos","_id":"multer-cos@1.0.2","_inBundle":false,"_integrity":"sha512-4F8P1VTCSNhiem+BFJFLe3Ixco6cIuAQ6j7U+PBRvdbBJRZgq5Q+vaDMMBWJ1HmPGOOP3AyKS5yk2f0nbFoqqA==","_location":"/multer-cos","_phantomChildren":{},"_requested":{"type":"tag","registry":true,"raw":"multer-cos","name":"multer-cos","escapedName":"multer-cos","rawSpec":"","saveSpec":null,"fetchSpec":"latest"},"_requiredBy":["#USER","/"],"_resolved":"https://registry.npmjs.org/multer-cos/-/multer-cos-1.0.2.tgz","_shasum":"95c7c06cdee1b9311675a895481f9d946de6dcf3","_spec":"multer-cos","_where":"/Users/lanbo/workplace/websocket","author":{"name":"lanbosm"},"bugs":{"url":"https://github.com/lanbosm/multer-COS/issues"},"bundleDependencies":false,"deprecated":false,"description":"Streaming multer storage engine for QCloud COS","devDependencies":{"cos-nodejs-sdk-v5":"^2.2.6","dotenv":"^5.0.1","multer":"^1.3.0"},"engines":{"node":">= 6.10.0"},"homepage":"https://github.com/lanbosm/multer-COS#readme","keywords":["express","multer","COS"],"license":"MIT","main":"index.js","name":"multer-cos","repository":{"type":"git","url":"git+ssh://git@github.com/lanbosm/multer-COS.git"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"version":"1.0.3","_lastModified":"2025-
|
|
1
|
+
{"_from":"multer-cos","_id":"multer-cos@1.0.2","_inBundle":false,"_integrity":"sha512-4F8P1VTCSNhiem+BFJFLe3Ixco6cIuAQ6j7U+PBRvdbBJRZgq5Q+vaDMMBWJ1HmPGOOP3AyKS5yk2f0nbFoqqA==","_location":"/multer-cos","_phantomChildren":{},"_requested":{"type":"tag","registry":true,"raw":"multer-cos","name":"multer-cos","escapedName":"multer-cos","rawSpec":"","saveSpec":null,"fetchSpec":"latest"},"_requiredBy":["#USER","/"],"_resolved":"https://registry.npmjs.org/multer-cos/-/multer-cos-1.0.2.tgz","_shasum":"95c7c06cdee1b9311675a895481f9d946de6dcf3","_spec":"multer-cos","_where":"/Users/lanbo/workplace/websocket","author":{"name":"lanbosm"},"bugs":{"url":"https://github.com/lanbosm/multer-COS/issues"},"bundleDependencies":false,"deprecated":false,"description":"Streaming multer storage engine for QCloud COS","devDependencies":{"cos-nodejs-sdk-v5":"^2.2.6","dotenv":"^5.0.1","multer":"^1.3.0"},"engines":{"node":">= 6.10.0"},"homepage":"https://github.com/lanbosm/multer-COS#readme","keywords":["express","multer","COS"],"license":"MIT","main":"index.js","name":"multer-cos","repository":{"type":"git","url":"git+ssh://git@github.com/lanbosm/multer-COS.git"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"version":"1.0.3","_lastModified":"2025-07-09T08:38:53.031Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"multer-s3","version":"3.0.1","description":"Streaming multer storage engine for AWS S3","main":"index.js","scripts":{"test":"standard && mocha test/basic.js"},"engines":{"node":">= 12.0.0"},"repository":{"type":"git","url":"git+https://github.com/badunk/multer-s3.git"},"keywords":["multer","s3","amazon","aws"],"author":"badunk","license":"MIT","bugs":{"url":"https://github.com/badunk/multer-s3/issues"},"homepage":"https://github.com/badunk/multer-s3#readme","dependencies":{"@aws-sdk/lib-storage":"^3.46.0","file-type":"^3.3.0","html-comment-regex":"^1.1.2","run-parallel":"^1.1.6"},"peerDependencies":{"@aws-sdk/client-s3":"^3.0.0"},"devDependencies":{"express":"^4.13.1","form-data":"^1.0.0-rc3","mocha":"^2.2.5","multer":"^1.1.0","on-finished":"^2.3.0","standard":"^5.4.1","xtend":"^4.0.1"},"_lastModified":"2025-
|
|
1
|
+
{"name":"multer-s3","version":"3.0.1","description":"Streaming multer storage engine for AWS S3","main":"index.js","scripts":{"test":"standard && mocha test/basic.js"},"engines":{"node":">= 12.0.0"},"repository":{"type":"git","url":"git+https://github.com/badunk/multer-s3.git"},"keywords":["multer","s3","amazon","aws"],"author":"badunk","license":"MIT","bugs":{"url":"https://github.com/badunk/multer-s3/issues"},"homepage":"https://github.com/badunk/multer-s3#readme","dependencies":{"@aws-sdk/lib-storage":"^3.46.0","file-type":"^3.3.0","html-comment-regex":"^1.1.2","run-parallel":"^1.1.6"},"peerDependencies":{"@aws-sdk/client-s3":"^3.0.0"},"devDependencies":{"express":"^4.13.1","form-data":"^1.0.0-rc3","mocha":"^2.2.5","multer":"^1.1.0","on-finished":"^2.3.0","standard":"^5.4.1","xtend":"^4.0.1"},"_lastModified":"2025-07-09T08:38:49.290Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"url-join","version":"4.0.1","description":"Join urls and normalize as in path.join.","main":"lib/url-join.js","scripts":{"test":"mocha --require should"},"repository":{"type":"git","url":"git://github.com/jfromaniello/url-join.git"},"keywords":["url","join"],"author":"José F. Romaniello <jfromaniello@gmail.com> (http://joseoncode.com)","license":"MIT","devDependencies":{"conventional-changelog":"^1.1.10","mocha":"^3.2.0","should":"~1.2.1"},"_lastModified":"2025-
|
|
1
|
+
{"name":"url-join","version":"4.0.1","description":"Join urls and normalize as in path.join.","main":"lib/url-join.js","scripts":{"test":"mocha --require should"},"repository":{"type":"git","url":"git://github.com/jfromaniello/url-join.git"},"keywords":["url","join"],"author":"José F. Romaniello <jfromaniello@gmail.com> (http://joseoncode.com)","license":"MIT","devDependencies":{"conventional-changelog":"^1.1.10","mocha":"^3.2.0","should":"~1.2.1"},"_lastModified":"2025-07-09T08:38:42.035Z"}
|
|
@@ -39,37 +39,129 @@ __export(attachments_exports, {
|
|
|
39
39
|
createMiddleware: () => createMiddleware
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(attachments_exports);
|
|
42
|
+
var import_stream = require("stream");
|
|
43
|
+
var import_mime_match = __toESM(require("mime-match"));
|
|
44
|
+
var import_mime_types = __toESM(require("mime-types"));
|
|
42
45
|
var import_utils = require("@nocobase/utils");
|
|
43
46
|
var import__ = __toESM(require(".."));
|
|
44
47
|
var import_constants = require("../../constants");
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
function makeMulterStorage(storage) {
|
|
49
|
+
const innerStorage = storage.make();
|
|
50
|
+
return {
|
|
51
|
+
_handleFile(req, file, cb) {
|
|
52
|
+
const pattern = storage.storage.rules.mimetype;
|
|
53
|
+
const peekSize = 4100;
|
|
54
|
+
const originalStream = file.stream;
|
|
55
|
+
const passThrough = new import_stream.PassThrough();
|
|
56
|
+
const proxyFile = { ...file, stream: passThrough };
|
|
57
|
+
let detectedMime = null;
|
|
58
|
+
const finalCallback = (err, result) => {
|
|
59
|
+
if (err) {
|
|
60
|
+
return cb(err);
|
|
61
|
+
}
|
|
62
|
+
if (detectedMime && result) {
|
|
63
|
+
result.mimetype = detectedMime;
|
|
64
|
+
}
|
|
65
|
+
cb(null, result);
|
|
66
|
+
};
|
|
67
|
+
innerStorage._handleFile(req, proxyFile, finalCallback);
|
|
68
|
+
const chunks = [];
|
|
69
|
+
let bytesRead = 0;
|
|
70
|
+
let validationTriggered = false;
|
|
71
|
+
const cleanup = () => {
|
|
72
|
+
originalStream.removeListener("data", onData);
|
|
73
|
+
originalStream.removeListener("end", onEnd);
|
|
74
|
+
originalStream.removeListener("error", onError);
|
|
75
|
+
};
|
|
76
|
+
const onData = (chunk) => {
|
|
77
|
+
if (validationTriggered) return;
|
|
78
|
+
chunks.push(chunk);
|
|
79
|
+
bytesRead += chunk.length;
|
|
80
|
+
if (bytesRead >= peekSize) {
|
|
81
|
+
validationTriggered = true;
|
|
82
|
+
cleanup();
|
|
83
|
+
originalStream.pause();
|
|
84
|
+
validate(Buffer.concat(chunks));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const onEnd = () => {
|
|
88
|
+
if (!validationTriggered) {
|
|
89
|
+
validationTriggered = true;
|
|
90
|
+
cleanup();
|
|
91
|
+
validate(Buffer.concat(chunks));
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const onError = (err) => {
|
|
95
|
+
cleanup();
|
|
96
|
+
passThrough.destroy(err);
|
|
97
|
+
};
|
|
98
|
+
const validate = async (header) => {
|
|
99
|
+
try {
|
|
100
|
+
const { fileTypeFromBuffer } = await import("file-type");
|
|
101
|
+
const type = await fileTypeFromBuffer(new Uint8Array(header));
|
|
102
|
+
if (type) {
|
|
103
|
+
detectedMime = type.mime;
|
|
104
|
+
} else {
|
|
105
|
+
const fromFilename = import_mime_types.default.lookup(file.originalname);
|
|
106
|
+
if (fromFilename) {
|
|
107
|
+
detectedMime = fromFilename;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!detectedMime || pattern !== "*" && !pattern.toString().split(",").some((0, import_mime_match.default)(detectedMime))) {
|
|
111
|
+
const err = new Error("Mime type not allowed by storage rule");
|
|
112
|
+
err.name = "MulterError";
|
|
113
|
+
originalStream.destroy();
|
|
114
|
+
passThrough.destroy();
|
|
115
|
+
return cb(err);
|
|
116
|
+
}
|
|
117
|
+
passThrough.write(header, (writeErr) => {
|
|
118
|
+
if (writeErr) {
|
|
119
|
+
originalStream.destroy();
|
|
120
|
+
passThrough.destroy();
|
|
121
|
+
return cb(writeErr);
|
|
122
|
+
}
|
|
123
|
+
if (originalStream.readableEnded) {
|
|
124
|
+
passThrough.end();
|
|
125
|
+
} else {
|
|
126
|
+
originalStream.pipe(passThrough);
|
|
127
|
+
originalStream.resume();
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
} catch (err) {
|
|
131
|
+
originalStream.destroy();
|
|
132
|
+
passThrough.destroy();
|
|
133
|
+
return cb(err);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
originalStream.on("data", onData);
|
|
137
|
+
originalStream.on("end", onEnd);
|
|
138
|
+
originalStream.on("error", onError);
|
|
139
|
+
},
|
|
140
|
+
_removeFile(req, file, cb) {
|
|
141
|
+
innerStorage._removeFile(req, file, cb);
|
|
142
|
+
}
|
|
52
143
|
};
|
|
53
144
|
}
|
|
54
145
|
async function multipart(ctx, next) {
|
|
146
|
+
var _a;
|
|
55
147
|
const { storage } = ctx;
|
|
56
148
|
if (!storage) {
|
|
57
149
|
ctx.logger.error("[file-manager] no linked or default storage provided");
|
|
58
150
|
return ctx.throw(500);
|
|
59
151
|
}
|
|
60
|
-
const
|
|
61
|
-
if (!
|
|
152
|
+
const StorageClass = ctx.app.pm.get(import__.default).storageTypes.get(storage.type);
|
|
153
|
+
if (!StorageClass) {
|
|
62
154
|
ctx.logger.error(`[file-manager] storage type "${storage.type}" is not defined`);
|
|
63
155
|
return ctx.throw(500);
|
|
64
156
|
}
|
|
65
|
-
const storageInstance = new
|
|
157
|
+
const storageInstance = new StorageClass(storage);
|
|
66
158
|
const multerOptions = {
|
|
67
|
-
fileFilter: getFileFilter(
|
|
159
|
+
// fileFilter: getFileFilter(storageInstance),
|
|
68
160
|
limits: {
|
|
69
161
|
// 每次只允许提交一个文件
|
|
70
162
|
files: import_constants.LIMIT_FILES
|
|
71
163
|
},
|
|
72
|
-
storage: storageInstance.make()
|
|
164
|
+
storage: ((_a = storage.rules) == null ? void 0 : _a.mimetype) ? makeMulterStorage(storageInstance) : storageInstance.make()
|
|
73
165
|
};
|
|
74
166
|
multerOptions.limits["fileSize"] = Math.max(import_constants.FILE_SIZE_LIMIT_MIN, storage.rules.size ?? import_constants.FILE_SIZE_LIMIT_DEFAULT);
|
|
75
167
|
const upload = (0, import_utils.koaMulter)(multerOptions).single(import_constants.FILE_FIELD_NAME);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-file-manager",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"displayName": "File manager",
|
|
5
5
|
"displayName.zh-CN": "文件管理器",
|
|
6
6
|
"description": "Provides files storage services with files collection template and attachment field.",
|
|
@@ -17,22 +17,28 @@
|
|
|
17
17
|
"@formily/shared": "2.x",
|
|
18
18
|
"@koa/multer": "^3.1.0",
|
|
19
19
|
"@types/koa-multer": "^1.0.4",
|
|
20
|
+
"@types/mime-types": "^3.0.1",
|
|
20
21
|
"@types/multer": "^1.4.5",
|
|
21
22
|
"antd": "5.x",
|
|
22
23
|
"axios": "^1.7.0",
|
|
23
24
|
"cos-nodejs-sdk-v5": "^2.11.14",
|
|
24
25
|
"koa-static": "^5.0.0",
|
|
25
26
|
"mime-match": "^1.0.2",
|
|
27
|
+
"mime-types": "^3.0.1",
|
|
26
28
|
"mkdirp": "~0.5.4",
|
|
27
29
|
"multer": "^1.4.5-lts.2",
|
|
28
30
|
"multer-aliyun-oss": "2.1.3",
|
|
29
31
|
"multer-cos": "^1.0.3",
|
|
30
32
|
"multer-s3": "^3.0.1",
|
|
33
|
+
"multistream": "^4.1.0",
|
|
31
34
|
"react": "^18.2.0",
|
|
32
35
|
"react-i18next": "^11.15.1",
|
|
33
36
|
"supertest": "^6.1.6",
|
|
34
37
|
"url-join": "4.0.1"
|
|
35
38
|
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"file-type": "^21.0.0"
|
|
41
|
+
},
|
|
36
42
|
"peerDependencies": {
|
|
37
43
|
"@nocobase/actions": "1.x",
|
|
38
44
|
"@nocobase/client": "1.x",
|
|
@@ -45,5 +51,5 @@
|
|
|
45
51
|
"Collections",
|
|
46
52
|
"Collection fields"
|
|
47
53
|
],
|
|
48
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "85bbe64895160a66603856c6ff0c05e4ebb5fbc2"
|
|
49
55
|
}
|