之前上传图片、文件一般都在七牛云,近期由于公司的服务器等资源全部都在阿里云,上传图片也改为了阿里云直传。我们目前采用的是服务器端签名后直传的方式,据说说下前端的实现:
刚开始我们采用的是没有处理图片信息,先请求接口从服务器端获取到阿里云的签名信息,然后直接上传的从本地获取到的file文件:
uploadImg() {
let data = this.data;//服务器返回给你的签名信息,因为我们是用vue是实现的,获取签名成功后数据保存在data里
const key = data.dir + new Date().getTime() + '_' + this.file.name;
var request = new FormData(),
request.append("OSSAccessKeyId", data.accessid); //Bucket 拥有者的Access Key Id。
request.append("policy", data.policy); //policy规定了请求的表单域的合法性
request.append("Signature", data.signature); //根据Access Key Secret和policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性
request.append("key", key); //文件名字,可设置路径
request.append("success_action_status", "200"); // 让服务端返回200,不然,默认会返回204
request.append('file', this.file);//需要上传的文件 file
axios({
url: data.host,//需要上传的阿里云url
data: request,
method: "post",
headers: { "Content-Type": "multipart/form-data" }//因为是formData形式上传的,所以需要加上这句
})
.then(res => {
return res.data;
})
.then(rst => {
this.imgUrl = data.host + "/" + key;
});
},
后来发现这种上传手机原图,图比较大的情况,上传会特别慢,从阿里云下载的时候图片加载也很影响用户体验,于是就加入了裁切和压缩图片的功能,我们运用的是vue的插件:vue-core-image-upload 首先安装:
npm install vue-core-image-upload --save然后编辑代码:
<\vue-core-image-upload 无需前边的’\‘ :class="['btn', 'btn-primary']" :crop="local" 图片本地裁切,服务器端裁切为“server” cropratio="1:1" 图片裁切比例 inputaccept="image/*" 接收的文件类型 :max-file-size="5242880" 图片的大小 :compress="60" 压缩比例,数字越小,压缩的越模糊 :isxhr="isXhr" 不使用插件自带的上传,自定义上传图片 @imagechanged="imagechanged" 当input框改变选择图片时候触发,会返回input的获取的图片数据 @imageuploading="imageuploading" 当图片上传过程中触发,你可以自定义你需要处理的内容比如显示加载动画等。>\<\ vue-core-image-upload>//无需“\”
\>\vue-core-image-upload>
js部分:
import VueCoreImageUpload from ‘core/vue-core-image-upload.vue’
export default {
components: {
‘vue-core-image-upload’: VueCoreImageUpload,
},
data() {
return {
}
},
methods: {
imageuploading() {
}
imagechanged(){
}
}
};
好了,到此本以为事情圆满解决了,却又发现了另外的问题,上传到阿里云是用formData的方式上传的,图片裁切过后得到的是Base64格式的图片,这时就需要把Base64格式的图片转成Blob格式,再使用formData方式上传
Base64格式转换为Blob:
function getBlobBydataURI(dataURI,type) {
var binary = atob(dataURI.split(‘,’)[1]);
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {type:type });
}
最后的上传代码js部分:(html部分如上)
import utils from “@/js/utils”;
import axios from “axios”;
import VueCoreImageUpload from “vue-core-image-upload”;
export default {
name: “”,
components: {
“vue-core-image-upload”: VueCoreImageUpload
},
data() {
return {
imgUrl:””
local: “local”,
isXhr: false,
file: “”,
data: “”,
isShowLoading: false
};
},
methods: {
imagechanged(data) {
this.file = data;
this.getOssToken();
},
imageuploading(data) {
this.isShowLoading = true;
},
uploadImg() {
let data = this.data;
const key = data.dir + new Date().getTime() + “.png”;//因为Base64格式的图片没有后缀,我们给默认png格式的图片
var $Blob = utils.getBlobBydataURI(this.file, “image/png”);
var request = new FormData()
request.append(“OSSAccessKeyId”, data.accessid); //Bucket 拥有者的Access Key Id。
request.append(“policy”, data.policy); //policy规定了请求的表单域的合法性
request.append(“Signature”, data.signature); //根据Access Key Secret和policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性
request.append(“key”, key); //文件名字,可设置路径
request.append(“success_action_status”, “200”); // 让服务端返回200,不然,默认会返回204
request.append(“file”, $Blob);
axios({
url: data.host,
data: request,
method: "post",
headers: { "Content-Type": "multipart/form-data" }
})
.then(res => {
return res.data;
})
.then(rst => {
this.imgUrl = data.host + "/" + key;
this.isShowLoading = false;
});
},
getOssToken() {//获取阿里云签名
this.$api.getOssToken().then(res => {
this.data = res;
this.uploadImg();
});
}
},
};
突然想起来阿里云上传还有个很大的坑,其实文档上有写,但是很多人忽略的问题:就是跨域,记得在你的阿里云上设置一下这个就好了
上传文件参考博客:https://gilea.cn/article/11399260-9be2-11e8-b2a2-b1037d08a2a6
vue上传裁切压缩图片插件文档:https://vanthink-ued.github.io/vue-core-image-upload/index.html#/cn/home