[eggjs/egg][Feature Request] egg-multipart插件,上传文件,文件名中文乱码

2024-08-05 398 views
4

比如我上传一个文件名为测试.txt的文件,返回内容如下

{
  field: 'file',
  filename: 'K�.txt',
  encoding: '7bit',
  mime: 'text/plain',
  fieldname: 'file',
  transferEncoding: '7bit',
  mimeType: 'text/plain',
  filepath: '/tmp/egg-multipart-tmp/manage/2020/08/13/14/04478617-6e3a-40a3-8291-32280d1a906e.txt'
}

filename为乱码,请问这个有处理方案吗?谢谢

回答

1

您好,复现步骤如下:

  1. 启动项目
  2. post请求调用api:http://localhost:7001/upload,form-data协议,上传文件,文件名为中文,比如:测试.txt
  3. 查看返回结果中的name字段 谢谢!
4

JUY6XQ5V3DCNCNYCM2FOJ@Q

5

你先确认下是不是 POSTMAN 的问题,抓包看下

8

2 这个是抓包的截图; 另外我问下您,您复现的时候,是不会出现中文乱码是吗?采用的什么方式调用的?

2

从单测和 CURL 来看是没问题的,应该是你 POSTMAN 的问题,发送的时候就乱码了。

  it('should POST /', async () => {
    const result = await app.httpRequest()
      .post('/upload')
      .attach('file', __dirname + '/测试.gif');

    assert(result.body[0].name === '测试.gif');
  });
curl -F "data=@/Users/tz/Desktop/测试.gif" localhost:7001/upload
7

PS: 你的 file 中间件是没啥意义的,要抽象代码也是写到 service,然后 Controller 直接调用。

还有 readFileSyncstatSync 这些 Sync 的方法,是绝对不能用的,都换为 promise 的方式吧。

当然这两个跟你的问题没关系。

9

好的,非常感谢您的解答和帮助!

2

大佬,再冒昧的问一句,这两个方法为啥不能用?是有什么隐患吗?因为有部分生产环境已经使用这些方法很久了,暂时没发现有什么问题,期待回复。

0

Sync 是同步方法,会阻塞其他请求

7

当系统遇到 filename*=UTF-8'' 这样的标头,问题得到重现。还没找到现有解决方案

来自 postman 生成的请求如下:

Content-Disposition: form-data; name="file"; filename="整改报告模版.jpg"; filename*=UTF-8''%E6%95%B4%E6%94%B9%E6%8A%A5%E5%91%8A%E6%A8%A1%E7%89%88.jpg
9

这标题很特殊。。。 有可能是 co-busbusy 等基础库处理的时候没处理好。

为什么会有这种头呢,前端最好处理下。

4

问题出在 busboy 库,对filename进行了两次 decode,因为出现了 两次 filename。下面贴出我的修改

diff --git a/node_modules/busboy/lib/types/multipart.js b/node_modules/busboy/lib/types/multipart.js
index b6d8e8b..d415020 100644
--- a/node_modules/busboy/lib/types/multipart.js
+++ b/node_modules/busboy/lib/types/multipart.js
@@ -156,6 +156,7 @@ function Multipart(boy, cfg) {
           if (RE_NAME.test(parsed[i][0])) {
             fieldname = decodeText(parsed[i][1], 'binary', 'utf8');
           } else if (RE_FILENAME.test(parsed[i][0])) {
+            if (filename !== undefined) continue;
             filename = decodeText(parsed[i][1], 'binary', 'utf8');
             if (!preservePath)
               filename = basename(filename);