
微信小程序上传图片到七牛云,小程序Webview嵌入H5上传图片&原生小程序上传图片
学东西当然要学以致用,最近在帮朋友做微信小程序,没有选择mpvue,因为时间紧加上不熟悉,怕遇到坑不能快速处理,拖了进度,所以采用了原生小程序+webview的方式做了第一版。
小程序webview上传图片
因为涉及到H5,所以图片上传这块就用到了微信中的jssdk,
第一步是wx.config配置
前端代码如下:
abp.services.app.wxAccess.getOfficialAccountJsdkConfig().done(function (data) {
if (data) {
var appId = data.appId;
var timestamp = data.timestamp;
var nonceStr = data.noncestr;
var signature = data.signature;
wx.config({
debug: false, //调试模式 当为tru时,开启调试模式
appId: appId,
timestamp: timestamp.toString(), //签名时间戳
nonceStr: nonceStr, //生成签名的随机串
signature: signature, //签名
jsApiList: ['chooseImage', 'uploadImage'],
success: function () {
alert("配置成功");
},
fail: function () {
alert("配置失败");
}
});
wx.ready(function () {
// 在这里调用 API
wx.checkJsApi({
jsApiList: [
'chooseImage',
'uploadImage'
],
success: function (res) {
//console.log(JSON.stringify(res));
}
});
});
wx.error(function(res){
alert(JSON.stringify(res));
});
}
});
后端代码:
/// <summary>
/// 获取公众号JsdkConfig
/// </summary>
/// <returns></returns>
public async Task<Dtos.GetOfficialAccountJsdkConfigOutput> GetOfficialAccountJsdkConfig()
{
var input = new Dtos.GetAccessInput
{
AppId = _appConfiguration["WechatOfficialAccount:AppId"],
Secret = _appConfiguration["WechatOfficialAccount:Secret"]
};
var noncestr = Guid.NewGuid().ToString("N");
var jsapi = await GetJsapiTicket(input);
//var timestamp = (DateTime.Now.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, 0).Ticks) / 10000000;
var timestamp = new Helper.UnixTime().DateTimeToUnix(DateTime.Now);
//var url = Request.UrlReferrer.OriginalString;
var url = _iHttpContextAccessor.HttpContext.Request.Headers[Microsoft.Net.Http.Headers.HeaderNames.Referer].ToString();
var shaStr = $"jsapi_ticket={jsapi.Permit}&noncestr={noncestr}×tamp={timestamp}&url={url}";
var signature = new Helper.Encrypt().Sha1Encrypt(shaStr);
return new Dtos.GetOfficialAccountJsdkConfigOutput
{
AppId = input.AppId,
Noncestr = noncestr,
Timestamp = timestamp,
Signature = signature
};
}
第二步就是调用jssdk
前端js代码如下:
wx.chooseImage({
count: 9,
needResult: 1,
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: function (data) {
//localIds = data.localIds[0]; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
for (var localId = 0; localId <= data.localIds.length - 1; localId++) {
if (isIOS) {
wx.getLocalImgData({
localId: data.localIds[localId], // 图片的localID
success: function (res) {
// var localData = res.localData; // localData是图片的base64数据,可以用img标签显示
//console.log(localData);
}
});
} else {
}
}
},
fail: function (res) {
alert(JSON.stringify(res));
//alterShowMessage("操作提示", JSON.stringify(res), "1", "确定", "", "", "");
}
});
jssdk中,如果是iOS的话,前端无法直接使用localIds资源id做展示,需要调用wx.getLocalImgData方法来获取图片的base64编码
提交前端选择的图片到服务端并由服务的上传到七牛云
前端部分代码:
wx.uploadImage({ //获取图片媒体ID
localId: localIds[erp.common.idx].toString(), // 需要上传的图片的本地ID
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) { //获取成功
// 上传序号,上传一张 累计 +1
erp.common.idx++;
//存储图片媒体ID,用,号分割
// serverIds += res.serverId + ',';
erp.common.serverIdsArr.push(res.serverId);
if (erp.common.idx < localIds.length) { //本地图片ID 还没全部获取完图片媒体ID
//调用上传递归函数
erp.common.wxUploadImg(localIds, callback);
} else {
//上传序号归零
erp.common.idx = 0;
//服务器csrf 验证字符串,如果后端框架没开启csrf,则不需要
//alert(erp.common.serverIdsArr);
abp.services.app.wxAccess.uploadMediaToQiniu({
WxMediaIds: mediaIds
}).done(function (data) {
var imageUrl = [];
for (var index = 0; index <= data.qiniuFiles.length - 1; index++) {
imageUrl.push(data.qiniuFiles[index].qiniuUrl);
}
$.hideLoading();
callback && callback(imageUrl);
}).always(function(){
$.hideLoading();
});
//serverIds = '';
erp.common.serverIdsArr.length = 0;
return true;
}
},
fail: function (res) { //获取多媒体id失败 返回错误代码
alert("上传失败,msg:" + JSON.stringify(res));
}
});
后端部分代码:
/// <summary>
/// 上传文件到七牛
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
//[RemoteService(false)]
public async Task<Dtos.UploadMediaToQiniuOutput> UploadMediaToQiniu(Dtos.UploadMediaToQiniuInput input)
{
var output = new Dtos.UploadMediaToQiniuOutput();
if (input.WxMediaIds.Count > 0)
{
output.QiniuFiles = new System.Collections.Generic.List<Dtos.QiniuFile>();
var access_token = await GetOfficialAccountAccessToken();
var accessKey = _appConfiguration["Qny:qiniuyunAK"];
var secretKey = _appConfiguration["Qny:qiniuyunSK"];
var bucket = _appConfiguration["Qny:qiniuyunBucket"];
var prefixPath = _appConfiguration["Qny:prefixPath"];
var qiniuStorage = new Helper.QiniuStorage(accessKey, secretKey, bucket);
foreach (var mediaId in input.WxMediaIds)
{
var url = $"https://api.weixin.qq.com/cgi-bin/media/get?access_token={access_token.Permit}&media_id={mediaId}";
var fileKey = qiniuStorage.UploadStream(url);
var fileUrl = $"{prefixPath}/{fileKey}";
output.QiniuFiles.Add(new Dtos.QiniuFile { QiniuUrl = fileUrl, WxMediaId = mediaId });
}
}
return output;
}
原生小程序上传图片到七牛云
后面考虑到一些交互上面的问题,就把原来的webview方式改成了全原生的模式。采用原生的方式,在图片上传上面就好处理多了,只需要实现获取到七牛云用于上传的token,然后使用wx.uploadFile即可上传。 服务端获取token代码:
/// <summary>
/// 获取七牛token
/// </summary>
/// <returns></returns>
public QiniuTokenOutputDto GetQiniuUpToken()
{
var accessKey = _appConfiguration["Qny:qiniuyunAK"];
var secretKey = _appConfiguration["Qny:qiniuyunSK"];
var bucket = _appConfiguration["Qny:qiniuyunBucket"];
var qiniuStorage = new Helper.QiniuStorage(accessKey, secretKey, bucket);
var output = new QiniuTokenOutputDto() { UpToken = qiniuStorage.CreateUploadToken() };
return output;
}
小程序端部分代码:
1、获取token
2、调用小程序API,选择图片。
wx.chooseImage({
count: 9-this.data.cardImgList.length, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], //从相册选择
success: (res) => {
res.tempFilePaths.forEach((item,index)=>{
that.upload2Qiniu(item);
});
}
});
}
/**
* 图片上传七牛云
*/
upload2Qiniu(tempFilePaths) {
let token = this.data.token;
var that = this;
wx.uploadFile({
url: 'https://up-z0.qiniup.com',
name: 'file',
filePath: tempFilePaths,
header: {
"Content-Type": "multipart/form-data"
},
formData: {
token: that.data.upToken,
},
success: function (res) {
let data = JSON.parse(res.data)
//data.hash图片的资源名,可直接通过域名加资源名访问
// to do ...
},
fail: function (res) {
console.log(res)
}
});
}
如果需要更详细的资料,那么就请自行百度or谷歌吧
我只是记录我的学习过程,由于书读得少,可能很多地方表述或者是理解得不对,请轻喷并指正。