Chrome 浏览器无法显示苹果上传图片的原因

Plan: Chrome 无法显示上传图片的根因诊断与修复

TLDR: HTTP 200 已确认表明 Express.static 静态服务正确找到了文件。

真正的问题是:iOS 设备在"高效格式"摄像模式下拍摄的照片实际是 HEIC/HEIF 格式 ,上传时浏览器或 iOS 仍以 .jpeg 作为文件名发送------Chrome 不支持 HEIC 格式解码,因此显示破损黑屏。

macOS Preview 和 Safari 原生支持 HEIC,所以文件在宿主机上看起来"存在且正常",但 Chrome 无法渲染。


第一阶段:确认根因

步骤 1 --- 在宿主机终端执行,确认文件真实格式:

bash 复制代码
file /文件路径/att-1774505932244-769917788.jpeg

若输出包含 HEIF image 或 ISO Media,则确认为 HEIC 格式。

步骤 2(可选确认) --- Chrome DevTools → Network → 找到该请求 → Response Headers → 确认 Content-Type: image/jpeg(MIME 类型是 jpeg,但内容是 HEIC 字节,Chrome 解码失败)。


第二阶段:修复

步骤 1 --- 安装 sharp 库(Node.js 图片处理,支持 HEIC→JPEG 转换):

bash 复制代码
npm install sharp
npm install --save-dev @types/sharp

步骤 2 --- 修改 attachment.controller.ts

在 Multer 完成文件写入磁盘之后、入库之前,用 sharp 将 HEIC/HEIF 文件就地转换为标准 JPEG。核心逻辑:

  • 判断 file.mimetype 是否为 image/heic 或 image/heif,或者检测文件头字节
  • 若是 HEIC,则用 sharp(file.path).jpeg().toFile(tmpPath) 转换后替换原文件
  • 更新 file.mimetype 为 image/jpeg,file.size 为转换后大小

步骤 3 --- 修改 main.ts

将 useStaticAssets 的相对路径改为绝对路径(Docker 环境最佳实践,避免 process.cwd() 在不同环境下解析不一致):

现状:

typescript 复制代码
app.useStaticAssets('uploads', { prefix: '/uploads' });

改为(在文件顶部 import join):

typescript 复制代码
import { join } from 'path';
// ...
app.useStaticAssets(join(__dirname, '..', 'uploads'), { prefix: '/uploads' });

__dirname 在 Docker 中为 /usr/src/app/dist,join(__dirname, '..', 'uploads') = /usr/src/app/uploads,与 Docker Volume 挂载路径完全一致。

步骤 4 --- 重新构建并启动容器:

bash 复制代码
docker-compose up --build

相关文件

  • main.ts --- 修改 useStaticAssets 路径为绝对路径
  • attachment.controller.ts --- 在 uploadFile 方法中添加 HEIC→JPEG 转换逻辑

验证步骤

  1. 先执行 file 命令确认 HEIC 假设成立
  2. 重建 Docker 镜像后,重新上传一张 iOS 照片
  3. 在 Chrome 中通过 URL 访问该图片,确认正常显示

决策说明

  • 不修改 Multer 的 destination 配置 :文件先存到 uploads/attachments/,存入后立即原地转换,文件名保持不变,路径不受影响
  • 对非图片文件(PDF 等):需在转换逻辑中判断 mimetype,跳过非图片类型
  • 旧的损坏文件:无需处理,用户只需重新上传即可

相关推荐
一水鉴天7 分钟前
统一对象拓扑(UOT)设计全链定稿:从三件事分离到三继承 之1 20261010(豆包“查看聊天内容”继续)
前端·css
栖凤18 分钟前
Java 的 try-catch 在 Agent 里失效了,我用了 5 个模式才兜住
java·前端·python
粥里有勺糖19 分钟前
视野修炼第136期 | 前端小恐龙"Deno"被收购
前端·github·ai编程
修炼的dance23 分钟前
页面塞了13.88 MB字体,导出的PDF只有71 KB
前端
qq_3691736324 分钟前
如何将 AI 生成的 HTML 网页发布成在线链接?不用自己搭建服务器
前端·人工智能·html·效率工具·html 发布
风花一世月31 分钟前
⚡ 我把一座含氢能源园区搬进了浏览器(五类能流实时算守恒,在线直接玩)
前端·人工智能
羲云1 小时前
Claude 越界事件之后:Agent 权限设计为什么不能只靠提示词
前端
行者全栈架构师1 小时前
【鸿蒙心迹】鸿蒙网络请求架构实战——@ohos.net.http 到 Axios 封装、拦截器与统一错误处理(HarmonyOS 7.x)
前端·算法·架构
全栈Agent 小李1 小时前
【无标题】
前端·后端·agent·ai编程·全栈·cursor·mcp
羲云1 小时前
别让 AI 凭记忆做调研:给 WorkBuddy 接上可核验的实时搜索
前端