用express的 res.download下载文件,中文文件名总是乱码啊 Nodejs

用express的 res.download下载文件,中文文件名总是乱码啊 Nodejs

用express的 res.download下载文件,中文文件名总是乱码啊,有什么解决的办法吗?对于这一块真是不懂啊

2 回复

当然可以!使用 expressres.download 方法下载带有中文文件名的文件时,经常会出现乱码问题。这是因为 HTTP 协议并没有明确规定如何处理非英文字符的文件名。不同浏览器对文件名编码的处理方式也有所不同。

解决方法

为了解决这个问题,我们可以手动设置 Content-Disposition 头,并确保文件名被正确地进行 URL 编码或 Base64 编码。

示例代码

假设我们有一个简单的 Express 应用程序,其中有一个路由用于下载文件:

const express = require('express');
const path = require('path');
const app = express();

app.get('/download/:filename', (req, res) => {
    const filename = req.params.filename;
    const filePath = path.join(__dirname, 'files', filename);

    // 获取客户端使用的浏览器类型
    const userAgent = req.headers['user-agent'];
    
    // 设置 Content-Disposition 头以支持中文文件名
    let encodedFilename = encodeURIComponent(filename);
    if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {
        // 对于 Safari 浏览器(不包括 Chrome)
        encodedFilename = encodedFilename.replace(/['()]/g, escape).replace(/\*/g, '%2A').replace(/%(?:7C|60|5E)/g, unescape);
    } else {
        // 其他浏览器(包括 Chrome 和 Firefox)
        encodedFilename = Buffer.from(filename, 'utf-8').toString('base64');
        encodedFilename = `filename*=UTF-8''${encodedFilename}`;
    }

    res.setHeader('Content-Disposition', `attachment; ${encodedFilename}`);
    res.download(filePath); // 发送文件
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 获取文件路径

    • 使用 path.join 来构建文件的完整路径。
  2. 处理文件名编码

    • 使用 encodeURIComponent 进行基本的 URL 编码。
    • 针对 Safari 浏览器,进行额外的编码转换,以避免一些特殊情况下的乱码。
    • 对于其他浏览器(如 Chrome 和 Firefox),使用 Base64 编码文件名,并添加 filename* 参数以指定 UTF-8 编码。
  3. 设置响应头

    • 使用 Content-Disposition 头来指定文件名,并确保其正确编码。

通过这种方式,可以确保大多数浏览器都能正确识别并显示中文文件名。


在使用 expressres.download 方法下载文件时,如果文件名包含中文字符,可能会出现乱码问题。这是因为 HTTP 协议本身不支持直接传输非 ASCII 字符,因此需要对文件名进行编码处理。

解决这个问题的方法是在调用 res.download 时,将文件名通过 URL 编码(即 % 编码)来传递,这样浏览器可以正确识别文件名。

示例代码

const express = require('express');
const path = require('path');
const app = express();

app.get('/download', (req, res) => {
    const fileName = '测试文件.txt';
    const encodedFileName = encodeURIComponent(fileName); // 对文件名进行编码
    res.download(path.join(__dirname, 'files', fileName), encodedFileName);
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 引入依赖:首先引入 expresspath 模块。
  2. 创建路由:定义一个 /download 路由,用于处理文件下载请求。
  3. 文件名编码:使用 encodeURIComponent 函数对文件名进行编码。这会将中文字符转换为 %E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt 这样的形式。
  4. 发送下载响应:调用 res.download 方法发送下载响应,并传入编码后的文件名作为 Content-Disposition 头的一部分,以确保浏览器能正确解析文件名。

通过这种方式,浏览器能够正确识别并显示中文文件名,从而避免了乱码问题。

回到顶部