uniapp小程序上传图片到aws,使用uni.uploadFile上传
此外,如果你的代码将在浏览器环境中运行,可能需要使用一个不同的加密库,因为crypto库是Node.js特有的。你的签名应该是用你的AWS Secret Access Key、日期、区域、服务和特定的签名字符串(在你的代码中是"aws4_request")进行的散列。比如,如果你在计算签名的时候包含了某个头部,但是在实际的请求中没有包含这个头部,那么就会导致签名错误。最开始搜索了方法,使用插件“a
在工作中遇到了需要小程序上传到AWS的问题。使用的是uni-app, v2。
最开始搜索了方法,使用插件“aws-sdk”,配合预签名URL 进行使用,后来报错,发现小程序的上传并不支持这个插件的使用,过程忘记保留了。
在社群论坛中看到一篇文章,发现------
只能使用最原始的uni.uploadFile()进行上传,只是需要配置不同的参数。
记录一下代码,关于原理和逻辑,还是多参考aws的官网
// 生成AWS S3 POST请求签名 --- 需要添加引入
import crypto from 'crypto-js'
这个方法的目的是生成一个签名密钥,以便用于请求签名。这是AWS Version 4签名过程的一部分。签名密钥是从您的AWS secret access key以及其他几个参数(日期、区域和服务)计算出来的。最后,这个签名密钥会用于计算签名哈希,该哈希会附加到请求中,以便AWS可以验证发送者的身份。 请注意,在实际使用中,必须更详细地处理错误和边缘情况,比如输入参数的验证等等。此外,如果你的代码将在浏览器环境中运行,可能需要使用一个不同的加密库,因为crypto库是Node.js特有的。
generateS3PostSignature() {
const dateStamp = dayjs().utc().format('YYYYMMDD');
const regionName = 'us-east-1'; // 可以替换自己的region
const serviceName = 's3';
const secretKey = 'xxxxxxxxxxxxxxx'; // 使用自己的secretKey
// 将policy转换为base64编码 --- policy政策 后文会提到,可修改
this.policyBase64 = Buffer.from(JSON.stringify(this.policy)).toString('base64');
// 获取签名密钥 ---自定义的方法 getSignatureKey
const signingKey = this.getSignatureKey(secretKey, dateStamp, regionName, serviceName);
// 计算签名
const signature = crypto.HmacSHA256(this.policyBase64, signingKey).toString(crypto.enc.Hex);
return signature;
},
// 获取signingKey的方法 --- getSignatureKey
getSignatureKey(key, dateStamp, regionName, serviceName) {
const kDate = crypto.HmacSHA256(dateStamp, 'AWS4' + key);
const kRegion = crypto.HmacSHA256(regionName, kDate);
const kService = crypto.HmacSHA256(serviceName, kRegion);
const kSigning = crypto.HmacSHA256('aws4_request', kService);
return kSigning;
},
// 此段代码格式参考了 Aws官方文档的方法
下边就是选择图片和上传图片或视频的内容了,顺序很重要,顺序很重要,顺序很重要~~
chooseImage(filePath, fileType, thumbTempFilePath) {
//thumbTempFilePath 视频的封面
if (fileType === 'video') {
this.imgTemporaryAddress = thumbTempFilePath
}
this.isUploadImg = true // 是否正在上传的flag
this.imgUuid = getUUID()
const date = dayjs().utc().format('YYYYMMDDTHHmmss') + 'Z';
this.policy = {
"expiration": "2099-12-30T12:00:00.000Z",// 截止日期
"conditions": [
{"bucket": "your-bucket"}, // 自己的bucket包名
["starts-with", "$key", ""],
{"acl": "public-read"}, // 一定要加,之前没加,有报错
["starts-with", "$Content-Type", fileType], // fileType 是从子组件传入的 可以是image 或者 video
{"x-amz-meta-uuid": this.imgUuid}, // 唯一性
{"x-amz-server-side-encryption": "AES256"},
["starts-with", "$x-amz-meta-tag", ""],
{"x-amz-credential": `密钥id/${dayjs().utc().format('YYYYMMDD')}/us-east-1/s3/aws4_request`}, // 使用密钥id进行拼接,/us-east-1/s3/ 这两个值要和之前使用的保持一直
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-date": date}
]
}
let index = filePath.lastIndexOf('/');
let fileKey = filePath.substring(index + 1); // 自己项目需要上传的字段
const secretAccessKey = 'your—secretAccessKey' // 传入自己的secretAccessKey
const signature = this.generateS3PostSignature(secretAccessKey) // 之前已经写过的方法
const formData = {
"key": fileKey,
"bucket": "your-bucket", // your-bucket
'policy': this.policyBase64, // 加密的政策信息
"Content-Type": fileType, // 文件类型
"acl": "public-read", // 添加ACL字段 !!一定要加
"x-amz-server-side-encryption": "AES256", // 加密方式,
"x-amz-meta-uuid": this.imgUuid,
// 拼接了实际访问的密钥ID
"x-amz-credential": `实际访问的密钥ID/${dayjs().utc().format('YYYYMMDD')}/us-east-1/s3/aws4_request`,
"x-amz-algorithm": "AWS4-HMAC-SHA256",
// "x-amz-content-sha256": "UNSIGNED-PAYLOAD",
"x-amz-meta-tag": "",
"x-amz-date": date,
"X-Amz-Signature": signature,
}
// 使用uni.uploadFile上传文件到服务器
const uploadTask = uni.uploadFile({
url: 'https://xxxxx.xxxx.com/', // 替换为处理文件上传的接口地址
filePath: filePath,
name: 'file',
formData: formData, // 之前的formData
success: res => {
if (res.success) {
this.isUploadImg = false // 关闭上传状态
// 文件上传到AWS成功,处理响应结果,进行自己的逻辑操作
} else {
uni.showToast({
title: '图片发送失败',
icon: 'none',
duration: 2500
})
this.isUploadImg = false
}
console.log(res, 'res')
},
fail: error => {
this.isUploadImg = false
console.error('文件上传失败', error)
}
})
uploadTask.onProgressUpdate((res) => {
this.uploadProgress = res.progress // 获取上传的进度 res的信息很多可以自行提取
// uploadTask.abort(); // 取消上传任务。
})
},
在上传成功之前,会有各种各样的问题~
关于算法的选择和使用,参考了Aws的建议
关于报错的展示,需要关注Code 和 Message标签的内容,只要是报错,都能去解决。
写这个文件最开始的时候,问题很多,完全没有报错展示,就是上传不了。
下图是AWS请求签名计算有问题,导致它与AWS期望的签名不匹配。
出现该问题可能是因为
-
密钥错误:你提供的AWS密钥(包括Access key和Secret key)可能是错误的。请确认你使用的密钥是否正确。
-
签名计算错误:你可能在计算签名的过程中犯了错误。你的签名应该是用你的AWS Secret Access Key、日期、区域、服务和特定的签名字符串(在你的代码中是"aws4_request")进行的散列。请确保这些值都是正确的,并且你正确地进行了计算。
-
时间错误:如果你的服务器时间和AWS服务器时间有较大的偏差,那么这也可能导致签名验证失败。确保你的服务器时间是正确的。
-
请求参数或头部错误:你在请求中设置的一些参数或者头部可能影响到了签名的计算。比如,如果你在计算签名的时候包含了某个头部,但是在实际的请求中没有包含这个头部,那么就会导致签名错误。你需要确保计算签名时使用的参数和头部与实际的请求完全一致。
当时卡在了policy对象编码成base64的问题~
更多推荐
所有评论(0)