You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:使用AWS Lambda+API Gateway上传S3的文件无法预览

问题描述

我通过AWS Lambda搭配API Gateway将图片、视频上传至S3 Bucket,上传流程显示成功且能在响应中获取到文件的Location链接,但点击链接无法预览图片,报错提示“图像无法显示,包含错误”。需要实现支持图片、音频及视频的正常上传与预览功能。


相关Lambda代码

const multipart = require('aws-lambda-multipart-parser');
const AWS = require('aws-sdk');
const { config } = require('./config')
const { v4: uuidv4 } = require('uuid')
const fs = require('fs');

const s3 = new AWS.S3({
  accessKeyId:config?.dev?.aws_s3?.ACCESS_KEY,
  secretAccessKey:config?.dev?.aws_s3?.SECRET_KEY
})


// 从事件中解析数据(event作为参数传入)
const result =  await multipart.parse(param);
let myFile= result.media.filename.split(".")
let fileType = myFile[myFile.length - 1];
const fileName = uuidv4()+'.'+fileType;


const uploadData = {
    Bucket : config?.dev?.aws_s3?.BUCKETNAME,
    Key : fileName,
    Body : Buffer.from(result.media.content, 'binary'),
    ContentType : result.media.contentType,
    ACL : 'public-read',
    Conditions: [
        ['content-length-range', 0, 10000000] // 10 Mb
    ]
}

try {
    const responseData = await s3.upload(uploadData).promise()
    return  {
        "body" : {
            "message" : "Image uploaded successfully",
            "data" : responseData
        },
        'statusCode': 200
    }
} catch (e) {
    return  {
        "body" : {
            "message" : e.message
        },
        'statusCode': 500
    }
}

上传请求截图

上传请求截图


响应结果

{
"message": "Image uploaded successfully",
"data": {
    "ETag": "\"662d32878c3e0628d2958e95fc055855\"",
    "Location": "https://bucketname.s3.amazonaws.com/03c2fcd1-ab92-42a8-93cf-d6a89545c77e.jpeg",
    "key": "03c2fcd1-ab92-42a8-93cf-d6a89545c77e.jpeg",
    "Key": "03c2fcd1-ab92-42a8-93cf-d6a89545c77e.jpeg",
    "Bucket": "bucketname"
}
}

解决方案

核心问题定位

代码中Buffer.from(result.media.content, 'binary')是导致文件损坏的直接原因:aws-lambda-multipart-parser解析后的文件内容本身已经是Buffer类型,强行用binary编码二次转换会破坏原始二进制数据,上传到S3的文件自然无法正常预览/播放。

另外,Conditions是生成预签名URL时的配置参数,s3.upload()方法并不需要该字段,应移除避免无效参数干扰。

修正后的代码

const multipart = require('aws-lambda-multipart-parser');
const AWS = require('aws-sdk');
const { config } = require('./config')
const { v4: uuidv4 } = require('uuid')

const s3 = new AWS.S3({
  accessKeyId:config?.dev?.aws_s3?.ACCESS_KEY,
  secretAccessKey:config?.dev?.aws_s3?.SECRET_KEY
})

// 从事件中解析数据(event作为参数传入)
const result =  await multipart.parse(param);
const myFile = result.media.filename.split(".")
const fileType = myFile[myFile.length - 1];
const fileName = uuidv4()+'.'+fileType;

// 文件大小校验(10MB)
const MAX_SIZE = 10 * 1024 * 1024;
if (result.media.content.length > MAX_SIZE) {
    return {
        body: { message: "文件大小不能超过10MB" },
        statusCode: 400
    };
}

// 文件类型校验(仅允许图片、音频、视频)
const allowedTypes = ['image/', 'audio/', 'video/'];
const isAllowed = allowedTypes.some(type => result.media.contentType.startsWith(type));
if (!isAllowed) {
    return {
        body: { message: "仅支持图片、音频、视频类型文件上传" },
        statusCode: 400
    };
}

const uploadData = {
    Bucket : config?.dev?.aws_s3?.BUCKETNAME,
    Key : fileName,
    Body : result.media.content, // 直接使用解析后的Buffer内容
    ContentType : result.media.contentType,
    ACL : 'public-read'
}

try {
    const responseData = await s3.upload(uploadData).promise()
    return  {
        body : {
            message : "文件上传成功",
            data : responseData
        },
        statusCode: 200
    }
} catch (e) {
    return  {
        body : {
            message : `上传失败:${e.message}`
        },
        statusCode: 500
    }
}

额外优化说明

  1. 文件类型校验:新增对contentType的校验,仅允许image/*、audio/*、video/*类型文件上传,避免非法文件流入。
  2. 文件大小校验:通过代码直接判断文件字节长度,替代无效的Conditions参数,确保大小限制生效。
  3. 错误信息优化:在捕获异常时补充错误前缀,让返回信息更直观。

验证方式

重新部署修正后的Lambda函数,上传图片、音频或视频文件:

  • 访问响应中的Location链接,确认图片可预览、音频/视频可正常播放;
  • 下载文件到本地,验证文件能正常打开,无损坏情况。

内容的提问来源于stack exchange,提问作者Vincent

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 12:45:32