Express响应动态文件名失效问题(部署于Google Cloud Run)
Express.js 动态文件名下载异常问题
问题现象
在Express.js(版本^4.17.1)中,使用静态文件名调用res.download时:
return res.download(filePath, 'test.pptx');
功能完全正常。但改用动态变量fileName调用时:
return res.download(filePath, fileName);
下载的文件名称会变成「download」,且响应中未返回Content-Disposition头。
完整处理代码
async function downloadPPT(req, res) { const readyFilesPath = path.resolve(pptProcessFolderPath, 'ready_files'); const files = fs.readdirSync(readyFilesPath); if(files.length > 1){ const zipFile = files.map(e => { return { path: path.resolve(readyFilesPath, e), name: e } }); return res.zip(zipFile, 'PPTs.zip'); } const filePath = path.resolve(readyFilesPath, files[0]) const fileName = files[0] return res.download(filePath, fileName); }
补充细节
- 仅在部署到Google Cloud Run的Docker容器中出现该问题,本地Docker运行无异常;
- 使用静态文件名部署在GCP时功能正常;
- Dockerfile配置如下:
FROM node:14 # Create app directory WORKDIR /home # Install app dependencies # A wildcard is used to ensure both package.json AND package-lock.json are copied # where available (npm@5+) COPY package.json ./ RUN npm install # If you are building your code for production # RUN npm ci --only=production # Bundle app source COPY . . EXPOSE 3000 CMD [ "npm", "start" ]
可行解决方向
- 处理文件名编码:Google Cloud Run环境对文件名编码处理可能存在差异,尝试对
fileName做URL编码后传入:
const encodedFileName = encodeURIComponent(fileName); return res.download(filePath, encodedFileName);
或手动设置响应头:
res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(fileName)}"`); return res.download(filePath);
校验文件名字符合法性:检查
files[0]是否包含空格、非ASCII等特殊字符,这类字符在GCP环境下可能被截断过滤,可对文件名做清理处理。显式设置响应头:GCP的负载均衡或Cloud Run可能修改响应头,尝试同时设置
Content-Type和Content-Disposition:
const fileExt = path.extname(fileName); const contentType = mime.getType(fileExt) || 'application/octet-stream'; res.setHeader('Content-Type', contentType); res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`); return res.sendFile(filePath);
内容的提问来源于stack exchange,提问作者Robert Ferreira
相关产品推荐
相关产品推荐

