我尼玛uni-app竟然没有支持h5图片上传的组件,呕心沥血的自己写了一个~~
思路:
- 首先将图片转成base64方式,再利用canvas进行图片压缩,避免图片太大上传超时
- 提交给后端php处理,由php上传到oss,然后返回路径
前端
<template>
<view>
<view class="collection-top-interval"></view>
<view class="collection-view">
<template>
<view>
res
</view>
<view class="year">
<view class="title">
<text style="">
图片上传
</text>
</view>
<view class="line1"></view>
<view class="year-info" style="position: relative;">
<img src="/static/image/property/add_image.png" style="width: 150upx;height: 160upx;margin-right: 36upx;" alt="">
<view v-for="(item,index) in temp_images" :key="index">
<img @click="preview(index)" :src="item" style="width: 150upx;height: 160upx;" alt="">
<img @click="delImg(index)" src="/static/image/property/error.png" style="position: relative;bottom:140upx;right: 24upx;width: 36upx;height: 36upx;">
</view>
<view ref="inputfile" id="inputfile" style="position: absolute; opacity: 0; "></view>
</view>
</view>
<view class="collection-top-interval"></view>
<button class="confirm" @click="next()">完成</button>
</template>
</view>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
temp_images : [],
driving_license : [],
compulsory_insurance : [],
res : '',
baseUrl : '',
isIOS : false
};
},
onShow(){
},
mounted() {
let myself = this;
//创建一个input上传框
var input = document.createElement('input')
input.type = 'file'
input.multiple = 'multiple';
input.onchange = (e) => {
let inputDOM = document.getElementById("inputfile");
//获取input元素
inputDOM = inputDOM.firstChild;
// 通过eDOM取文件数据
for(var i = 0;i < inputDOM.files.length;i++){
this.file = inputDOM.files[i];
//new一个FileReader实例
let reader = new FileReader();
reader.readAsDataURL(this.file) //base 64读取
reader.onload=function(e){
//最多上传三张,你可以自己定义
if(myself.temp_images.length < 3){
//this.result 就是base64图片地址,对图片进行压缩
myself.compress(this.result,800,1).then(function (val) {
//压缩后的图片
var baseUrl = val;
uni.showLoading({
title: '加载中'
});
//将图片转交给后端处理
uni.request({
url: 'https://your_domain.com/api.php/yearly/upload',
method: 'POST',
data: {
value : baseUrl,
},
success: res => {
uni.hideLoading();
res = res.data;
if(res.code == 1){
myself.driving_license.push(res.data);
myself.temp_images.push(baseUrl);
}
uni.showToast({
title: res.msg,
duration: 1000,
icon: 'none'
});
},
fail: (res) => {
myself.res = res;
},
complete: () => {}
});
});
}
}
}
}
//将input追加到view中
this.$refs.inputfile.$el.appendChild(input);
var inputfile = document.getElementById("inputfile");
inputfile = inputfile.firstChild;
inputfile.style.width = '63px';
inputfile.style.height = '63px';
},
computed: {
},
onLoad(e) {
this.isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
},
methods: {
//利用canvas对图片进行压缩
compress(base64String, w, quality) {
var myself = this;
var getMimeType = function (urlData) {
var arr = urlData.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
return mime;
};
var newImage = new Image();
var imgWidth, imgHeight;
var promise = new Promise(resolve => newImage.onload = resolve);
newImage.src = base64String;
return promise.then(() => {
imgWidth = newImage.width;
imgHeight = newImage.height;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
if (Math.max(imgWidth, imgHeight) > w) {
if (imgWidth > imgHeight) {
canvas.width = w;
canvas.height = w * imgHeight / imgWidth;
} else {
canvas.height = w;
canvas.width = w * imgWidth / imgHeight;
}
//如果是安卓客户端的话,将图片分辨率*2
if(!myself.isIOS){
canvas.height = canvas.height * 2;
canvas.width = canvas.width * 2;
}
} else {
canvas.width = imgWidth;
canvas.height = imgHeight;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(newImage, 0, 0, canvas.width, canvas.height);
var base64 = canvas.toDataURL(getMimeType(base64String), quality);
return base64;
});
},
preview(index) {
uni.previewImage({
current : index,
urls : this.temp_images
})
},
goBack() {
uni.navigateBack({
delta: 1
});
},
delImg(index){
uni.showLoading({
title: '加载中'
});
uni.request({
url: 'https://your_domain.com/api.php/yearly/delImage',
method: 'POST',
data: {
img_url : this.driving_license[index].split("com/")[1],
},
success: res => {
uni.hideLoading();
res = res.data;
if(res.code == 1){
this.temp_images.splice(index,1);
this.driving_license.splice(index,1);
}
uni.showToast({
title: res.msg,
duration: 1000,
icon: 'none'
});
},
fail: (res) => {
myself.res = res;
},
complete: () => {}
});
}
}
};
</script>
<style lang="scss">
@import "./index.css";
</style>
CSS
.collection-top-interval {
height: 13px;
width: 100%;
background-color: #f0f0f0;
margin-top:0upx;
}
.collection-view {
position: relative;
font-family: PingFang-SC-Bold;
}
.line{
padding: 0px !important;
margin: 0px !important;
height:1px;
width: 100%;
background:rgba(238,238,238,1);
}
.line1{
padding: 0px !important;
margin-left: 24upx;
width:702upx !important;
height:1px;
background:rgba(238,238,238,1);
}
.year{
display: flex;
flex-direction: column;
}
.year>view{
margin-left: 20upx;
padding: 40upx 0upx;
display: flex;
flex-direction: row;
position: relative;
width: 100%;
}
input{
border: 0px;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.title text{
width:300upx;
height:31upx;
font-size:32upx;
font-family:PingFang SC;
font-weight:bold;
color:rgba(51,51,51,1);
line-height:30upx;
}
.year-info>text{
height:27upx;
font-size:28upx;
font-family:PingFang SC;
font-weight:500;
color:rgba(51,51,51,1);
line-height:27upx;
float: left;
}
.confirm{
width:750upx;
height:108upx;
line-height: 108upx;
border-radius: 0px;
background:rgba(255,72,0,1);
font-family:PingFang SC;
font-weight:500;
color:rgba(255,255,255,1);
margin-top: 20upx;
position: fixed;
bottom: 0px;
}
.add-one{
width: 127upx !important;
height: 127upx !important;
}
PHP
public function upload(){
//实例化oss类
$Oss = new Oss();
//获取base64地址
$value = input('value');
$reg = '/data:image\/(\w+?);base64,(.+)$/si';
//获取文件后缀名
preg_match($reg,$value,$match_result);
$file_name = date('YmdHis').$this->codeMaking().'.'.$match_result[1];
//上传到oss的目录
$logo_path = 'uploads/yearly/'.date('Ymd');
//开始上传
$result = $Oss->putObject(base64_decode($match_result[2]),$logo_path,$file_name);
$this->success('成功',str_replace('http','https',$result['info']['url']));
}
public function delImage(){
//获取需要删除的文件
$img_url = input('img_url');
$Oss = new Oss();
//开始删除
$result = $Oss->delObject($img_url);
$this->success('成功');
}
OSS类
use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Core\OssUtil;
class Oss
{
private $ossClient;
private $bucket;
function __construct(){
$config = config('aliyun_oss_config');
$this->ossClient = new OssClient($config['accessKeyId'],$config['accessKeySecret'],$config['endpoint']);
$this->bucket = $config['bucket'];
}
/**
* 上传内存中的内容
* @param $tmp_name
* @param $path
* @param $file_name
* @return null
* @throws OssException
*/
public function putObject($tmp_name,$path,$file_name){
$result = $this->ossClient->putObject($this->bucket, $path.'/'.$file_name, $tmp_name);
return $result;
}
public function delObject($img_url){
$result = $this->ossClient->deleteObject($this->bucket,$img_url);
return $result;
}
}