主要功能:调用微信图片选择接口,用户确定之后将图片上传到七牛云,然后将返回的图片地址保存到本地数据库对应字段
踩的坑
- 微信JSDDK 1.1.0和1.2.0的差异
- 安卓手机和IOS的差异
主要表现在wx.chooseImage
和wx.uploadImage
,还有选择图片之后获取到如: wxlocalresource://imageid123456789987654321
这样的图片地址,IOS无法预览,或者wx.uploadImage
接口在IOS上只能上传一张图片。
实现的思路
- 通过
wx.chooseImage
接口让用户选择图片,选择之后生成预览 - 通过
wx.uploadImage
接口将图片上传到微信服务器做临时素材 - 通过七牛云fetch接口去下载微信服务器上的图片
代码实现
引入权限验证
// config权限验证
function wxconfig(url){
$.post('/weixin/configvalid', {'url':url.toString()}, function(data){
wx.config({
debug: false,
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
/* jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage']*/
jsApiList: [
'checkJsApi',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone',
'hideMenuItems',
'showMenuItems',
'hideAllNonBaseMenuItem',
'showAllNonBaseMenuItem',
'translateVoice',
'startRecord',
'stopRecord',
'onVoiceRecordEnd',
'playVoice',
'onVoicePlayEnd',
'pauseVoice',
'stopVoice',
'uploadVoice',
'downloadVoice',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage',
'getNetworkType',
'openLocation',
'getLocation',
'hideOptionMenu',
'showOptionMenu',
'closeWindow',
'scanQRCode',
'chooseWXPay',
'openProductSpecificView',
'addCard',
'chooseCard',
'openCard',
'openAddress',
'getLocalImgData'
]
});
});
}
导包 (这里我们用微信JSJDK 1.2.0)
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
选择图片,上传图片参考官方demo(我是遇到了一大箩筐问题之后才看到这个救命的demo)
// 5 图片接口
// 5.1 拍照、本地选图
var images = {
localId: [],
serverId: []
};
document.querySelector('#chooseImage').onclick = function () {
wx.chooseImage({
success: function (res) {
images.localId = res.localIds;
alert('已选择 ' + res.localIds.length + ' 张图片');
}
});
};
// 5.3 上传图片
document.querySelector('#uploadImage').onclick = function () {
if (images.localId.length == 0) {
alert('请先使用 chooseImage 接口选择图片');
return;
}
var i = 0, length = images.localId.length;
images.serverId = [];
function upload() {
wx.uploadImage({
localId: images.localId[i],
success: function (res) {
i++;
alert('已上传:' + i + '/' + length);
images.serverId.push(res.serverId);
if (i < length) {
upload();
}
},
fail: function (res) {
alert(JSON.stringify(res));
}
});
}
upload();
};
这个上传的例子可以解决图片只能上传一张的问题,我们就基于这个例子改进我们的代码。
wxconfig(window.location);
// 5 图片接口
// 5.1 拍照、本地选图
var images = {
localId: [],
serverId: []
};
var arrayImgs = new Array();
document.querySelector('#uploaderInput').onclick = function () {
wx.chooseImage({
success: function (res) {
images.localId = res.localIds;
//生成预览 区分一下ios跟其他系统
var localIds = res.localIds;
if(window.__wxjs_is_wkwebview){
//alert(localIds[0])
for (id in localIds) {
wx.getLocalImgData({
localId: localIds[id],
success: function (res) {
var localData = res.localData;
localData = localData.replace('jgp', 'jpeg');
var tmpl = '<img class="weui-uploader__file weui-uploader__file_status" src="'+localData+'" data-src="'+localIds[id]+'"/>';
$("#uploaderFiles").append(tmpl)
},
fail:function(res){
alert(res.errMsg);
}
});
}
}else{
//遍历数组
for (id in localIds){
var tmpl = '<img class="weui-uploader__file weui-uploader__file_status" src="#url#" data-src="#url#"/>';
$("#uploaderFiles").append($(tmpl.replace(/#url#/ig, localIds[id])));
}
}
}
});
};
// 5.3 上传图片
document.querySelector('#upload_img1').onclick = function () {
if (images.localId.length == 0) {
alert('请先选择图片');
return;
}
var i = 0, length = images.localId.length;
images.serverId = [];
function upload() {
wx.uploadImage({
localId: images.localId[i],
success: function (res) {
arrayImgs[i] = res.serverId
console.log(typeof(arrayImgs))
i++;
//alert('已上传:' + i + '/' + length);
images.serverId.push(res.serverId);
if (i < length) {
upload();
}else{
// 循环结束
topost(arrayImgs)
}
},
fail: function (res) {
alert(JSON.stringify(res));
}
});
}
upload();
};
最后向后台服务器发送请求
function topost(obj){
var resImgurl = obj.join(",")
$.ajax({
url: '/qiniuImg',
data: {
"resImgurl":resImgurl,
"content":"测试"
},
type: 'post',
dataType: 'json',
cache: false,
success: function(data){
console.log(data)
if(data.re){
console.log("成功写入数据库,进行页面跳转!")
alert(data.msg)
location.replace('/index');
}else{
alert(data.msg)
}
}
});
}
后台获取图片
String resImgurl = getPara("resImgurl");
// 获取图片信息
List<String> imgurl = new ArrayList<String>();
int i = 0;int j = 1;
String[] media_list = resImgurl.split(",");
for (String media_id : media_list) {
String key = QianNiuUpload.fetchTmpFile(media_id, "");
String url = QianNiuUpload.domain + key;
imgurl.add(url);
}
....
将图片的url 写入数据库
QianNiuUpload.java
public class QianNiuUpload {
//设置好账号的ACCESS_KEY和SECRET_KEY
public static String ACCESS_KEY = "xxxxxx";
public static String SECRET_KEY = "xxxxxx";
//要上传的空间
public static String bucketname = "xxxxxx";
public static String domain = "http://xxxxxxx.com/"; // 空间的域名
//上传到七牛后保存的文件名
public static String key = "随意,这个例子我们没用到";
//上传文件的路径
public static String FilePath = "随意,这个例子我们没用到";
//密钥配置
public static Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
//第二种方式: 自动识别要上传的空间(bucket)的存储区域是华东、华北、华南。
public static Zone z = Zone.autoZone();
public static Configuration c = new Configuration(z);
//创建上传对象
private static UploadManager uploadManager = new UploadManager(c);
//简单上传,使用默认策略,只需要设置上传的空间名就可以了
public static String getUpToken() {
return auth.uploadToken(bucketname);
}
public static void upload() throws IOException {
try {
//调用put方法上传
Response res = uploadManager.put(FilePath, key, getUpToken());
//打印返回的信息
System.out.println(res.bodyString());
} catch (QiniuException e) {
Response r = e.response;
// 请求失败时打印的异常的信息
System.out.println(r.toString());
try {
//响应的文本信息
System.out.println(r.bodyString());
} catch (QiniuException e1) {
//ignore
}
}
}
//定义两个成员变量常量
//获取临时素材(视频不能使用https协议)
public static final String GET_TMP_MATERIAL = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s";
//获取临时素材(视频)
public static final String GET_TMP_MATERIAL_VIDEO = "http://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s";
//获取微信服务器中生成的媒体文件
//由于视频使用的是http协议,而图片、语音使用http协议,故此处需要传递media_id和type
public static String fetchTmpFile(String media_id, String type){
try {
String token = AccessTokenApi.getAccessToken().getAccessToken();
String url = null;
//视频是http协议
if("video".equalsIgnoreCase(type)){
url = String.format(GET_TMP_MATERIAL_VIDEO, token, media_id);
}else{
url = String.format(GET_TMP_MATERIAL, token, media_id);;
}
URL Nurl = new URL(url);
//构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(Zone.autoZone());
Auth me = Auth.create(ACCESS_KEY,SECRET_KEY);
BucketManager bucketManager = new BucketManager(me, cfg);
// bucketManager.fetch("外源图片地址", "要上传的七牛目标资源文件夹", "文件名");
// 这边的文件名如果省略 七牛会随机给个名字
FetchRet fetchRet = bucketManager.fetch(url,bucketname);
//System.out.println(fetchRet.hash);
System.out.println(fetchRet.key);
//System.out.println(fetchRet.mimeType);
//System.out.println(fetchRet.fsize);
return fetchRet.key;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
java 后台七牛返回的上传后的文件名
七牛云存储空间可以看到图片已经成功上传了