Skip to content

亚马逊文件上传

将亚马逊文件上传 相关代码 归纳成一个 aws.js插件文件,大家可直接使用此文件调用即可。

aws.js 对应代码如下

js
import crypto from "crypto-js"
import dayjs from "dayjs"
import x2js from 'x2js'
const uploadFileToAWS = async (filePath, callback) => {
    let { data } = await apiGetAwsProperties()
    let index = filePath.lastIndexOf('/')
    let fileKey = filePath.substring(index+1)
    await uploadToS3(filePath, fileKey, data.sessionToken, data.bucketName, data.region, data.accessKeyId, data.secretAccessKey, callback)
}
// http://bucket.s3.region.amazonaws.com -> http://sigv4examplebucket.s3.ap-northeast-1.amazonaws.com
const uploadToS3 = async (filePath, fileKey, token, bucket, region, accessKeyId, secretAccessKey, callback) => {
    let x2jsInstance = new x2js()
    let prefix = ""
    let index = fileKey.lastIndexOf('.')
    fileKey = fileKey.substring(index)
    let name = dayjs.utc().format('YYYYMMDDHHmmss')+'_'+random_number(6)+fileKey
    let key = prefix ? prefix+name : name
    let url = `http://${bucket}.s3.${region}.amazonaws.com`
    // 终端节点endpoint: s3.ap-northeast-1.amazonaws.com
    let formData = getAWSFormData(prefix, key, token, bucket, region, accessKeyId, secretAccessKey)
    let fileUrl = ''
    await uni.uploadFile({
        url,
        filePath,
        name: 'file',
        formData,
        timeout: 10000,
        success: async (res) => {
            // console.log('上传成功', res);
            // 解析 XML 响应
            let json = x2jsInstance.xml2js(res.data)
            fileUrl = json?.PostResponse?.Location ?? ''
            // console.log("json=", json)
            // console.log("fileUrl=", fileUrl)
            if (fileUrl) {
                callback ? callback({fileUrl: fileUrl}) : ''
            }
        },
        fail: (error) => {
            // 在这里可以处理上传失败的情况
            console.error('上传失败', error);
        },
    });
}
const getAWSFormData = (prefix, key, token, bucket, region, accessKeyId, secretAccessKey) => {
    let fileType = "image/jpg,image/png"
    let serviceName = "s3"
    let expiration = "2099-12-30T12:00:00.000Z"
    let date = dayjs.utc().format('YYYYMMDDTHHmmss') + 'Z'
    let today = dayjs.utc().format('YYYYMMDD')
    let credential = `${accessKeyId}/${today}/${region}/s3/aws4_request`
    let policyBase64 = getPolicyBase64(prefix, today, date, '', bucket, token, region, accessKeyId, expiration)
    let signature = generateS3PostSignature(today, policyBase64, region, serviceName, secretAccessKey)
    let formData = {
        "key": key,
        "bucket": bucket,
        "acl": "public-read",
        "x-amz-server-side-encryption": "AES256",
        "x-amz-credential": credential,
        "x-amz-algorithm": "AWS4-HMAC-SHA256",
        "x-amz-date": date,
        "x-amz-meta-tag": "",
        "x-amz-security-token": token,
        "x-amz-content-sha256": "UNSIGNED-PAYLOAD",
        "success_action_status": "201",
        "policy": policyBase64,
        "x-amz-signature": signature,
    }
    return formData
}
const getPolicyBase64 = (prefix, today, date, fileType='', bucket, token, region, accessKeyId, expiration) => {
    // 拼接实际访问的密钥ID
    let credential = `${accessKeyId}/${today}/${region}/s3/aws4_request`
    let policyBase64 = ""
    let policy = {
        expiration: expiration,
        conditions: [
            { "bucket": bucket }, // 替换为你的 S3 存储桶名称
            ['starts-with', '$key', prefix],
            { "acl": 'public-read' },
            {"x-amz-server-side-encryption": "AES256"},
            ["starts-with", "$x-amz-meta-tag", ""],
            {"x-amz-credential": credential},
            {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
            {"x-amz-date": date },
            {"x-amz-content-sha256": "UNSIGNED-PAYLOAD"},
            { "success_action_status": "201"},
            {"x-amz-security-token": token}
        ],
    }
    console.log("policy=", policy)
    // 将policy 转换成base64编码 ---- policy政策
    policyBase64 = Buffer.from(JSON.stringify(policy)).toString('base64')
    
    return policyBase64
}
const getSignatureKey = (today, secretAccessKey, regionName, serviceName) => {
    let kDate = crypto.HmacSHA256(today, "AWS4" + secretAccessKey)
    let kRegin = crypto.HmacSHA256(regionName, kDate)
    let kService = crypto.HmacSHA256(serviceName, kRegin)
    let kSigning = crypto.HmacSHA256("aws4_request", kService)
    return kSigning
}
const generateS3PostSignature = (today, policyBase64, regionName, serviceName, secretAccessKey) => {
    // 获取签名密钥 
    let signingKey = getSignatureKey(today, secretAccessKey, regionName, serviceName)
    // 计算签名
    let signature = crypto.HmacSHA256(policyBase64, signingKey).toString(crypto.enc.Hex)
    return signature
}
// 此方法通过 接口 获取 亚马逊 相关配置
function apiGetAwsProperties (body = {
}, options = {
}) {
  const url = 'user/config/getAwsConfig';
  return http.post(url, { ...body, ...options }, { custom },)
}

export default uploadFileToAWS

调用操作

此示例,在 uniapp 里 调用 aws.js

import uploadFileToAWS from "./aws"
uni.chooseImage({
    count: 1,
    success: async (res) => {
        let filePath = res.tempFilePaths[0]
        filePath ? uploadFileToAWS(filePath, (d) => {
            d ? 
            (
                console.log("d.fileUrl=", d.fileUrl)
            ) : ''
        }) : ''
    }
})

创作不易请尊重他人劳动成果,未经授权禁止转载!
Released under the MIT License.