项目场景:
uniapp 图片 上传 阿里 OSS 对象存储
需求描述:
H5移动端开发中需要用户上传图片头像、身份证件等需求时。需要将图片上传至阿里oss中存储,并且下载到当前页面进行展示。
解决方案:
代码如下:
需要用到的依赖包:
npm install ali-oss --save
npm install lrz --save
创建一个 upload.js 文件:
const OSS = require("ali-oss");
const lrz = require('lrz');
var client = new OSS({region: "oss-cn-beijing", endpoint: "https://oss-cn-beijing.aliyuncs.com", accessKeyId: "xxxxxxxxxxxxxxxxxx", accessKeySecret: "xxxxxxxxxxxxxxxxxxxxx", bucket: "xxxx", secure: true
});export function uploadImg(e, filename, tag, imgpath, fn) {uni.showLoading({title: '正在上传...'});if (e.tempFiles.length == 0) {uni.hideLoading();uni.showToast({title:'未找到图片',icon:'none'})};let file = e.tempFiles[0];if (file.size > 15728640) { uni.showToast({title: "您上传的图片文件过大,请重新上传!",icon: "none"});return false}lrz(file, {width: 500,}).then(function(res) {let base64 = res.base64;let blob = convertBase64UrlToBlob(base64);let r = Math.random().toString(16).substr(2);let time = new Date(),y, m, d;y = time.getFullYear();m = String(time.getMonth() + 1).length === 2 ? (time.getMonth() + 1) : "0" + (time.getMonth() + 1);d = String(time.getDate()).length === 2 ? (time.getDate()) : "0" + time.getDate();let dfilefold = y + m + d; let name;if (imgpath.indexOf(filename) != -1) {let tmps = imgpath.split(filename)[1].split('?')[0]; name = filename + tmps;} else {name = filename + dfilefold + '/' + r;}client.put(name, blob).then(result => {uni.hideLoading();let path = result.url;fn(tag, path);}).catch(err => {console.log(err)uni.showToast({title: "图上传失败,请重试!",icon: "none"})});})
}
function convertBase64UrlToBlob(urlData) {var bytes &#61; window.atob(urlData.split(&#39;,&#39;)[1]); var ab &#61; new ArrayBuffer(bytes.length);var ia &#61; new Uint8Array(ab);for (var i &#61; 0; i < bytes.length; i&#43;&#43;) {ia[i] &#61; bytes.charCodeAt(i);}return new Blob([ab], {type: &#39;image/png&#39;});
};
在uniapp 项目组件中
<template><view><view><image class&#61;"" :src&#61;"idImage1" mode&#61;"aspectFit" v-if&#61;"idImage1">image><text class&#61;"" style&#61;"font-size: 100rpx;"&#64;tap&#61;"uploadImgfn(&#39;myImage/&#39;, 1, idImage1)" v-else />view><view><image class&#61;"" :src&#61;"idImage1" mode&#61;"aspectFit" v-if&#61;"idImage2">image><text class&#61;"" style&#61;"font-size: 100rpx;"&#64;tap&#61;"uploadImgfn(&#39;myImage/&#39;, 2, idImage2)" v-else />view>......view>
template>
<script>import {uploadImg} from "../../../utils/upload.js";data() {return {idImage1: " ", idImage2:&#39;&#39; &#39;&#39;, idImage3:&#39;&#39; &#39;&#39;, };},methods&#xff1a;{uploadImgfn(filename, tag, imgpath) {let that &#61; this;uni.chooseImage({success: (res) &#61;> {console.log(res);uploadImg(res, filename, tag, imgpath, function(tag, path) {if (tag &#61;&#61; 1) {that.idImage1 &#61; path &#43; "?" &#43; Date.now();} else if (tag &#61;&#61; 2) {that.idImage1 &#61; path &#43; "?" &#43; Date.now();} else if (tag &#61;&#61; 3) {that.idImage3 &#61; path &#43; "?" &#43; Date.now();}})}});},}
</script>
优化部分
感兴趣的小伙伴可以尝试一下封装成Promise对象&#xff0c;这样就用传递回调函数fn&#xff0c;也不用传递tag参数。在.then&#xff08;&#xff09;就可以给idImage进行赋值 url
有更好、更加简洁的方法希望大家能给我提出宝贵的意见或链接。