众多app都有修改个人头像需求,最近项目需要发布H5端,却发现上传头像图片文件不行。原因是再H5端,调用uni.canvasToTempFilePath方法后,得到的是base64图片数据,而不是图片缓存路径。而uni.uploadFile需要的是图片缓存路径。至此陷入漫长的寻找解决方案的过程。。。。
网上一些资料都是说做成formData的方式上传,这个方向是OK的,但是uniapp不支持new FormData(); 和 new window.FormData() 。 new window.FormData() 虽然不报错,但是上传的时候却把formData解析成对象,服务器(又拍云)拿不到base64的图片数据。
经过三天不断地尝试,结果发现,不用new window.FormData() 也行,直接用对象存储,作为formData的参数值上传即可。下面直接上代码:
在canvasToTempFilePath的成功回调里调用下面这个方法:
upGoodsloadImgs(imageSrc) {
uni.showLoading({
title: '图片上传中。。。',
mask: "true"
});
var that = this;
console.log("图片源路径:" + imageSrc)
var blobData = '';
var myFormdata = {};
// #ifdef APP-PLUS
var hz = imageSrc.substring(imageSrc.lastIndexOf('.'));
// #endif
// #ifdef H5
var arr = imageSrc.split(',');
var mime = arr[0].match(/:(.*?);/)[1]
var bstr = atob(arr[1]);//这个网上抄的,不太明白什么作用,没有它还不行,有知道的请不吝指教
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);//
}
blobData = new Blob([u8arr], {
type: mime
});
myFormdata.file = blobData;
console.log("that.imageName = " + that.imageName);
var hz = mime.split('/')[1] //获得后缀
imageSrc = '';
// #endif
var nowd = new Date();
var imgName = 'avatar' + nowd.getFullYear().toString() + (nowd.getMonth() + 1) + nowd.getDate() + nowd
.getHours() + nowd.getMinutes() + nowd.getSeconds() + (nowd.getTime() % 1000).toString() + '.' + hz;
var imgUrl = '/samxiche/' + imgName;
that.upyun.upload({
localPath: imageSrc,
remotePath: imgUrl,
success: function(res) {
console.log("图片上传成功:图片链接 = " + imgUrl);
console.log("返回的上传结果:", res);
var resImgInfo = JSON.parse(res.data);
var url = that.imgBaseHost + resImgInfo.url;
console.log("图片链接:", url);
let pages = getCurrentPages(); //获取所有页面栈实例列表
let nowPage = pages[pages.length - 1]; //当前页页面实例
let prevPage = pages[pages.length - 2]; //上一页页面实例
prevPage.$vm.avatarurl = url; //修改上一页datad的变量值
uni.navigateBack({ //uni.navigateTo跳转的返回,默认1为返回上一级
delta: 1
});
},
fail: function(errMsg) {
console.log("图片上传失败:", errMsg);
}
}, myFormdata ? myFormdata : '')
},
下面是又拍云的上传代码:
Upyun.prototype.upload = function (options, formParams) {
var self = this
console.log("this.bucket = " + this.bucket)
console.log("this.operator = " + this.operator)
console.log("this.getSignatureUrl = " + this.getSignatureUrl)
console.log("options.remotePath = " + options.remotePath)
var date = (new Date()).toGMTString()
var opts = {
'save-key': options.remotePath,
bucket: self.bucket,
expiration: Math.round(new Date().getTime() / 1000) + 3600,
date: date
}
var policy = Base64.encode(JSON.stringify(opts))
var data = [ 'POST', '/' + self.bucket, date, policy ].join('&')
self.getSignature(data, function (err, signature) {
if (err) {
console.log("获取图片上传签名失败!!!", err)
options.fail && options.fail(err)
options.complete && options.complete(err)
return
}
// #ifdef APP-PLUS
console.log("APP方式上传。。。。。。")
uni.uploadFile({
// url: `https://v0.api.upyun.com/${self.bucket}`,
url: `https://v0.api.upyun.com/${self.bucket}`,
filePath: options.localPath,
name: 'file',
formData: {
authorization: `UPYUN ${self.operator}:${signature}`,
policy: policy,
},
success: options.success,
fail: options.fail,
complete: options.complete
})
// #endif
// #ifdef H5
console.log("H5方式上传。。。。。。")
// formParams.append("authorization", `UPYUN ${self.operator}:${signature}`);
// formParams.append('policy', policy);
//这个formParams就是一个JSON对象,上面FormData方式的不行
formParams.authorization = `UPYUN ${self.operator}:${signature}`;
formParams.policy = policy;
console.log("要上传的formData:", formParams);
//uploadFIle接口直接不要filePath参数,就放一个formData就行。
uni.uploadFile({
// url: https://v0.api.upyun.com/${self.bucket}
,
url: https://v0.api.upyun.com/${self.bucket}
,
name: 'file',
formData: formParams,
success: options.success,
fail: options.fail,
complete: options.complete
})
// #endif
})
}
附件压缩包是完整的代码,两个js文件。配置好自己的又拍云图片空间 和 获取访问密钥的接口就行。