Node.js搭配Axios下载图片时如何从URL获取正确图片扩展名
解决方案
方案1:基于响应头Content-Type映射(实现成本最低,99%场景可用)
服务器返回的图片响应头默认会携带Content-Type字段,直接对应图片的MIME类型,提前维护MIME到扩展名的映射表即可匹配到正确后缀。
实现代码如下:
const axios = require('axios'); const fs = require('fs'); // MIME类型到扩展名的映射表,可按需扩展支持更多格式 const mimeExtMap = { 'image/jpeg': 'jpg', 'image/png': 'png', 'image/gif': 'gif', 'image/webp': 'webp', 'image/bmp': 'bmp', 'image/svg+xml': 'svg' }; const config = { responseType: 'stream' }; async function getImage(url) { const time = Math.floor(Date.now() / 1000) const resp = await axios.get(url, config) // 从响应头获取图片MIME类型 const contentType = resp.headers['content-type'] // 匹配扩展名,匹配不到默认用jpg,也可根据需求抛出异常拒绝非图片请求 const ext = mimeExtMap[contentType] || 'jpg' resp.data.pipe(fs.createWriteStream(`${time}.${ext}`)) // 可选:监听流写入完成/错误事件做后续处理 resp.data.on('end', () => console.log('图片保存完成')) resp.data.on('error', (err) => console.error('图片保存失败', err)) }
方案2:基于文件魔数校验(准确率100%,适配极端场景)
如果遇到服务器返回的Content-Type错误的情况,可以直接读取图片二进制文件的头部魔数判断格式,不受响应头和URL的影响。
可以直接用第三方库file-type实现,也可原生手写魔数判断逻辑,基于file-type的实现代码如下:
首先安装依赖:npm install file-type
代码实现:
const axios = require('axios'); const fs = require('fs'); const { fileTypeFromStream } = require('file-type'); const config = { responseType: 'stream' }; async function getImage(url) { const time = Math.floor(Date.now() / 1000) const resp = await axios.get(url, config) // 从流中读取文件头判断格式 const fileType = await fileTypeFromStream(resp.data) const ext = fileType?.ext || 'jpg' // 拼接已被读取的文件头字节后写入文件 resp.data.unshift(fileType._buffer) resp.data.pipe(fs.createWriteStream(`${time}.${ext}`)) }
注意事项
- 高并发场景下仅用时间戳作为文件名可能出现重复,可拼接随机字符串避免冲突
- 可增加非图片类型的过滤逻辑,避免恶意请求存入非法文件
- 可以按需调整映射表支持更多罕见图片格式
内容的提问来源于stack exchange,提问作者domskat
相关产品推荐
相关产品推荐

