React通过Node预签名URL上传S3图片丢失文件后缀问题求助
解决S3预签名URL上传丢失文件扩展名问题
问题根源在于后端生成S3对象的Key时仅使用了UUID,未拼接文件扩展名,且前端未将文件的扩展名信息传递给后端,导致S3中存储的文件无后缀,无法被正确识别类型。以下是具体修改方案:
后端修改
- 调整预签名URL生成服务,接收前端传来的文件扩展名,拼接在UUID后作为S3对象的
Key - 修改接口控制器,获取前端传递的扩展名参数
修改服务层代码
const getSignedUrlService = async (fileExt) => { // 拼接UUID与扩展名,生成带后缀的文件名 const imageName = `${crypto.randomUUID()}.${fileExt}` const params = ({ Bucket: config.awsS3.bucketName, Key: imageName, Expires: 120 // 有效期(秒) }) const uploadUrl = await s3.getSignedUrlPromise('putObject', params) // 可选:返回生成的文件名,方便后续存储到业务数据库 return { uploadUrl, key: imageName } }
修改控制器代码
// My controller try { // 从请求Query参数中获取前端传来的文件扩展名 const { fileExt } = req.query; const payload = await AwsS3Service.getSignedUrlService(fileExt); res.status(200).send({ success: true, data: payload }); // 其他逻辑... } catch (err) { // 错误处理... }
前端修改
- 请求预签名URL时,将文件的扩展名通过Query参数传递给后端
- 修正PUT请求的
Content-Type为文件本身的MIME类型,直接上传文件对象(无需FormData) - 修正状态变量的类型定义,避免类型错误
修正状态变量定义
// 原final类型为FileList,实际存储的是单个File对象,修正类型 const [final, setFinal] = useState<File | null>(null) const [img, setImg] = useState<string | null>(null)
修改文件选择事件处理
const handleImageChange = (e: ChangeEvent<HTMLInputElement>) => { const file = e.target.files?.[0] if (!file) return setFinal(file) const { type, name } = file setImgName(name) setImgType(type) const fileReader = new FileReader() fileReader.onload = (e) => { setImg(e.target?.result as string) } fileReader.readAsDataURL(file) }
修改提交事件处理
const handleFormSubmit: SubmitHandler<IImage> = async (data: IImage) => { if (!final) return try { // 提取文件扩展名 const fileExt = final.name.split('.').pop() if (!fileExt) { alert('无法识别文件扩展名') return } // 请求预签名URL,传递扩展名参数 const signedUrlRes = await axios({ method: 'GET', url: `${config.API_URL}/awss3`, params: { fileExt } }) // 直接上传文件对象,Content-Type设为文件自身的MIME类型 const resUpload = await fetch(signedUrlRes.data.data.uploadUrl, { method: 'PUT', headers: { 'Content-Type': final.type }, body: final }) if (resUpload.status === 200) { // 可选:将signedUrlRes.data.data.key(带扩展名的文件名)保存到业务数据库 // 页面跳转逻辑... } } catch(err: any) { alert(`An error occured. ${err.message}`) } }
修改完成后,S3中存储的文件将带有正确的扩展名(如9c9743b9-4dd7-4afa-af06-c060fb0fb175.png),文件类型也会被正确识别。
内容的提问来源于stack exchange,提问作者dEBA M
相关产品推荐
相关产品推荐

