Node.js服务端图片下载成功但无法显示 提示不支持文件格式
问题根本原因
你下载得到的文件本质就不是图片,和你改什么文件扩展名没有关系。
核心问题出在:Node原生的https.get方法默认不会自动跟随HTTP重定向,而你用的Unsplash下载链接不会直接返回图片二进制内容,会先返回301/302类的重定向响应,引导请求跳转到真实的CDN图片地址。你当前代码直接把重定向响应的返回内容(是跳转提示文本/HTML内容,不是图片数据)写入了jpg文件,不管你把后缀改成jpeg、jpg还是png,文件本身的内容不符合图片编码格式,图片查看器自然无法识别。
你可以直接用文本编辑器打开之前下载的损坏图片,大概率能看到HTML标签或者重定向相关的文本内容,就能直接验证这个判断。
另外你代码里手动在finish事件里调用fileStream.close()是多余操作,pipe传输完成后写入流会自动关闭,手动触发反而可能在极端情况下导致文件内容截断。
修复方法
给下载逻辑加上重定向跟随处理即可:拿到响应后先判断状态码,如果是重定向类型,就读取响应头里的location字段,递归请求新的地址,直到拿到状态码为200的真实图片流,再写入文件。
修正后的完整代码参考:
const express = require('express'); const app = express(); const https = require('https'); const fs = require('fs'); const cors = require('cors'); const pathh = require('path') // CORS配置 app.use(cors()); // JSON解析中间件 app.use(express.json()); function download(targetUrl, savePath) { const fileStream = fs.createWriteStream(savePath) const sendRequest = (url) => { https.get(url, (res) => { // 识别重定向状态码,递归跳转 if ([301, 302, 303, 307, 308].includes(res.statusCode)) { res.resume() // 消费当前响应数据,避免内存泄漏 sendRequest(res.headers.location) return } // 拿到200响应才是真实图片流,写入文件 if (res.statusCode === 200) { res.pipe(fileStream) fileStream.on('finish', () => { console.log('图片下载完成,保存路径:', savePath) }) return } // 其他错误状态码:销毁流、删除残留的损坏文件 fileStream.destroy() fs.unlink(savePath, () => {}) console.error('下载失败,响应状态码:', res.statusCode) }).on('error', (err) => { fileStream.destroy() fs.existsSync(savePath) && fs.unlinkSync(savePath) console.error('下载请求出错:', err.message) }) } sendRequest(targetUrl) } // 执行下载 const imgUrl = 'https://unsplash.com/photos/3aqiY4t1qxM/download?ixid=MnwxMjA3fDB8MXxhbGx8Mnx8fHx8fDJ8fDE2NTY3Njg2Mzc&force=true' const savePath = pathh.resolve("./pictures/renamed/", 'imageWorld.jpg') download(imgUrl, savePath) // 生产环境静态资源配置 if(process.env.NODE_ENV === 'production'){ app.use(express.static('client/build')); app.get('*', (req, res) =>{ res.sendFile(pathh.resolve(__dirname, 'client', 'build', 'index.html')) }); } const port = process.env.PORT || 5000; app.listen(port, () => console.log(`Server started on port ${port}`));
额外提示:你原代码中引入了
body-parser包但没有做任何挂载使用,属于冗余代码,可以直接删除,不影响任何功能。
内容的提问来源于stack exchange,提问作者night_programmer
相关产品推荐
相关产品推荐

