小程序上传图片到阿里云(UniApp)

371 阅读3分钟

引入阿里云生成签名的包(如果是后端生成则不需要)

  1. npm安装需要的模块
npm install crypto-js --save
 npm install js-base64 --save
  1. 创建Upload.js
  2. 在Upload.js 引入安装的包
import Base64 from './js-base64.js';
import Crypto from 'crypto-js';
  1. 设置阿里云的配置项
//阿里云的前缀地址
const fileHost = "https://xxx.oss-xxx.aliyuncs.com"
const env = {
  uploadImageUrl: 'ddriver/questionimg/', //文件存放的位置 前面无需加/
  AccessKeySecret: 'xxx',  // 阿里云账号的密码
  OSSAccessKeyId: 'xxx',// 阿里云账号
  timeout: 87600 //这个是上传文件时Policy的失效时间
};
  1. 设置该文件上传的最大时长(env.timeout)和文件限制 (需在该时间节点内上传完)
const getPolicyBase64 = function() {
	let date = new Date();
        // 当前的时间戳加上配置项的超时时间
	date.setHours(date.getHours() + env.timeout);
	let srcT = date.toISOString();
	const policyText = {
		"expiration": srcT, //设置该Policy的失效时间
		"conditions": [
			["content-length-range", 0, 5 * 1024 * 1024] 
                        // 设置上传文件的大小限制,5mb
		]
	};
	const policyBase64 = Base64.encode(JSON.stringify(policyText));
	return policyBase64;
}
  1. 根据配置生成阿里云签名
const getSignature = function(policyBase64) {
	const accesskey = env.AccessKeySecret;
	return Crypto.enc.Base64.stringify(Crypto.HmacSHA1(policyBase64, accesskey));
}
  1. 创建上传文件函数
/**
 * @param {Object} 
 * url: 本地临时文件路径如 wx:file...xxxx.png 注意!在模拟器上上传的图片地址并无
     wx:// 要做好处理
 * imgStr: 去掉前缀的图片路径 xxxx.png
 * imgStr 是去掉前缀的文件路径 
 * 这里传未处理的文件地址是因为上传时需用到完整路径
 * 这里又传了去掉前缀的文件地址是可以灵活的设置保存的文件名
 * */
const uploadFile = function(params) {
	const aliyunFileKey = params.imgStr
	const aliyunServerURL = env.uploadImageUrl;
	const accessid = env.OSSAccessKeyId;
	// 根据设置的超时时间生成PoLicy
	const policyBase64 = getPolicyBase64();
	// 再根据base64编码后的Policy生成签名
	const signature = getSignature(policyBase64);
        //为了避免代码重复性
	const fail = () => uni.showToast({
		title:'上传失败,请稍后再试',
		icon:'none'
	})
        // 将返回的函数设置为Promise
	return new Promise((resolve, reject) => {
		wx.uploadFile({
			url: fileHost, // 网站的前缀
			filePath: params.url, // 要保持的本地文件地址
			fileType: 'image', // 如果要传视频则 将其改成video
			name: 'file',// 必传项
			formData: {
                                // 上传到服务器的名字 
                                ///aliyunServerURL是文件夹名 如果上传到根目录则不传 
				'key': aliyunServerURL + aliyunFileKey,
                                // 文件配置项
				'policy': policyBase64,
                                // 阿里云账号
				'OSSAccessKeyId': accessid,
                                // 上面获得的签名
				'signature': signature,
                                //设置文件上传成功的状态码 默认创建成功返回的状态码为 204
				'success_action_status': '200', 
			},
                        // 成功的回调
			success: res => {
				console.log('上传成功', res);
				if (res.statusCode != 200) {
					fail()
					reject(res)
				} else {
					resolve(res)
				}
			},
                        // 失败的回调
			fail: err => {
				fail()
				reject(err)
			},
		})
	})
}
  1. 导出
export {
	uploadFile
}
  1. 在需要用到的地方引入该文件
	import {
		uploadFile
	} from './Upload.js'

10.调用

await new Promise(async (resolve) => {
   //因为在小程序内每次只能上传单张 所以循环调上传图片接口
   arr.forEach(async (item, index) => {
       // 获取的图片临时地址
   const url = arr[index].file.path
       // RemoveTempStr = function(str) {
   // return /wxfile/.test(str) ? str.replace("wxfile://", '') :  
       // str.replace(/^http:\/\/(tmp|temp|)\/(\S+)/, '$2')}
   const imgStr = this.RemoveTempStr(url)
       // 这里传未去掉前缀的文件地址
   await uploadFile({
               url,
               imgStr
       })
           .then(res => {
               index === arr.length - 1 ? resolve( '全部上传完成') : null;
           }).catch(err => {
                       console.log('错误', err);
                       IsErr = true
                       return
                   })
                 // 判断是否循环完毕
               })
               if (IsErr) {
                           await this.ShowModal('网络异常,请稍后再试')
                           CancelDisplay()
                           return
                       }
               })
      // someting to do ...