You need to enable JavaScript to run this app. 使用apollo-upload-client上传S3后图片URL无法正常显示问题
优惠活动
大模型
产品
解决方案
定价
更多

使用apollo-upload-client上传S3后图片URL无法正常显示问题

问题修复方案

你遇到的问题是S3中存储的文件内容/元数据异常,导致浏览器无法识别为图片,按以下优先级排查修复即可:

1. 补全S3上传参数

你当前的上传代码遗漏了ContentEncoding配置,从你提供的File对象可以看到文件编码为7bit,未配置的情况下S3会使用默认编码解析文件,导致浏览器识别错误。同时建议给S3的Key增加文件后缀,避免部分CDN/浏览器识别异常:

export async function uploadImageResolver(
  _parent,
  { file }: MutationUploadImageArgs,
  context: Context,
): Promise<string> {
  // identify(context);

  // 新增解构encoding
  const { createReadStream, filename, mimetype, encoding } = await file;
  // 提取文件后缀
  const fileSuffix = filename.split('.').pop();

  const response = await s3
    .upload({
      ACL: 'public-read',
      Bucket: environment.bucketName,
      Body: createReadStream(),
      Key: `${uuid()}.${fileSuffix}`, // 新增后缀
      ContentType: mimetype,
      ContentEncoding: encoding, // 新增编码配置
    })
    .promise();

  return response.Location;
}

修改后先测试,若仍异常继续往下处理。

2. 流转Buffer后再上传

部分版本的apollo-upload-client/graphql-upload返回的ReadStream直接传给S3 SDK时会出现内容截断/格式异常,将流转为Buffer后再上传即可解决:

export async function uploadImageResolver(
  _parent,
  { file }: MutationUploadImageArgs,
  context: Context,
): Promise<string> {
  const { createReadStream, filename, mimetype, encoding } = await file;
  const fileSuffix = filename.split('.').pop();

  // 流转Buffer
  const chunks = [];
  for await (const chunk of createReadStream()) {
    chunks.push(chunk);
  }
  const fileBuffer = Buffer.concat(chunks);

  const response = await s3
    .upload({
      ACL: 'public-read',
      Bucket: environment.bucketName,
      Body: fileBuffer, // 替换为Buffer
      Key: `${uuid()}.${fileSuffix}`,
      ContentType: mimetype,
      ContentEncoding: encoding,
    })
    .promise();

  return response.Location;
}

3. 检查Apollo Server上传配置

如果你使用的是Apollo Server 3及以上版本,框架默认禁用了内置上传功能,未手动配置上传中间件的情况下解析出的文件流本身就是错误的,需要按以下步骤配置:

  1. 安装依赖
npm install graphql-upload
  1. 修改服务启动配置
import { ApolloServer } from 'apollo-server-express';
import { graphqlUploadExpress } from 'graphql-upload';

const server = new ApolloServer({
  typeDefs,
  resolvers,
  uploads: false, // 禁用默认上传逻辑
});

// 启动服务后注册上传中间件
await server.start();
app.use(graphqlUploadExpress({ 
  maxFileSize: 10 * 1024 * 1024, // 按需设置最大文件大小,示例为10MB
  maxFiles: 10 
}));
server.applyMiddleware({ app });

完成以上配置后即可正常上传可访问的图片。你也可以直接在S3控制台对比代码上传的文件和手动上传的文件元数据差异,快速定位问题。


内容的提问来源于stack exchange,提问作者Michal Ružička Ružička

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 23:24:03