移动端微信图片上传

最近做项目,其中有个需求是在微信企业号上实现图片上传操作。一开始我就把重点放在了"移动端图片上传"而不是"微信图片上传",所以各种查资料,找插件,费了好些功夫,实现起来也是各种困难。后来接触到微信公众号,稍微了解了一下,才知道利用微信公众号或者现在已经升级为企业微信的企业号的API,还是挺简单的一个功能。下面我就详细整理一下整个过程,做个笔记,一方面可以帮助到从未接触过这个功能的同学,一方面也方便自己日后翻阅。
1、首先进入微信公众平台,查看JS-SDK开发文档。https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
2、开发文档有详细的步骤说明,但我还是根据我自己做的过程再稍微记录一下。
第一步中的绑定安全域名可不做,不会影响功能的实现。我直接从第二部引进js文件开始的。当我们想要通过微信上传图片时,有两种方法:一种是JS文件调用,一种是接口调用。这里用的是第一种,通过引进JS文件,然后直接调用接口,不再使用URL等接口地址。
3、JS文件的引入:

图1-引进JS文件

4、通过config接口注入权限验证配置:
这一步尤为重要。

图2-配置信息

1)在开发调试时,可将debug设为true,这样可以看到返回的信息,方便调试bug。但在生产环境上,记得设为false。
2)appId是公众号的唯一标识。项目挂靠在哪个公众号或者企业号,就去找相关负责人拿到appId,这个是固定的值,没有改动,也不需要调用获取。(服务器端,也就是后端开发人员去拿到这个值)
3)除了jsApiList的值需要前端人员根据需要自己写以外,其他参数均需从后端获取。最重要的是其中的签名串,有其特定的生成规则,后端需要根据一定的规则,去调用微信的接口,获取相关参数后生成签名串,然后再将对应的参数传给前端。前端人员获取到这些数据信息后,就可以完成配置信息的注入了。

图3-调用配置接口

4)可能会遇到的问题,当在完成配置信息的注入后,实际开始调用所需接口时,出现报错信息:invalid signature,permission denied,此时解决方法如下:
①首选检查生成签名串的算法(规则)是否正确;
② 其次需要特备注意的是:你在利用参数生成签名的时候,要对所有待签名参数按照字段名的 ASCII 码从小到大排序(字典序)后,使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串 string1。这里需要注意的是所有参数名均为小写字符。
③注意参数key值大小写问题;
④生成签名串时,需要前端人员给后端传当前页面的URL,但不包括'#'hash后面的部分。注意前端传值时的格式以及后端接收时的解析方式。
⑤确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
⑥很重要的一点,确认当前访问页面的URL已经被项目挂靠的公众号或者企业号授权访问。
更多错误信息及详细解决方法,请参考:https://my.oschina.net/u/2308739/blog/371414
5)jsApiList中需要填写的接口。(其实按现在这个操作,是不需要下载图片接口的,因为下载这一操作是由后端实现的。)
图4-jsApiList中的接口

5、配置信息注入并且成功校验完之后,就可以在wx.ready接口下操作相关图片接口了。

图5-wx.ready接口

6、在wx.ready下调用图片选择、上传、预览等接口时,直接按照操作的顺序调用即可。但其中涉及到的一个问题是,如果前端没有自己的后台,需要和另外一台服务器上的后台进行交互,此时在图片上传时就需要调用后端接口,将图片上传后生成的文件流,最终得到的mediaId传给后端,然后让后端去微信服务器上下载刚刚上传的图片。
7、话不多说,直接上全部代码。

 /** ******************获取微信配置数据********************** */
      var Url = ""; //服务器接口路径
      var oldNet = '';
      var newNet = '';//记录网络状态
      var configData;
      $.ajax({
            url: Url + '/GetSignatureInfo',//后端接口名,可自定义。
//            data: {pageUrl: location.href.split('#')[0]},
            type:"get",
            //params意为参数,是自定义的,用以表明这是传给后台的数据。
            data:{"params":location.href.split('#')[0]},
            contentType:"application/json; charset=utf-8",
            //数据类型为jsonp,解决跨域问题。
            dataType:"jsonp",
            //自定义的jsonp回调函数名,默认为jQuery自动生成的随机函数
            jsonpCallback:"success_jsonpCallback_select",
            //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为callback)
            jsonp:"callbackparam",
            success: function (data) {
//            alert(JSON.stringify(data));
              configData = {
                    debug : false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: data.appid, // 必填,公众号的唯一标识
                    timestamp: data.timestamp, // 必填,生成签名的时间戳
                    nonceStr: data.nonceStr, // 必填,生成签名的随机串
                    signature: data.signature,// 必填,签名,见附录1
                    jsApiList : ['chooseImage','previewImage','uploadImage','downloadImage']
                    // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                };
               
               //step2:注入配置信息
               wx.config(configData);
               //step3:通过ready接口处理成功验证
               wx.ready(function () {
                   // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
//                 alert("执行ready方法");
//                 wx.checkJsApi({
//                      jsApiList: ['chooseImage'] // 需要检测的JS接口列表,所有JS接口列表见附录2,
//                      success: function(res) {
//                      // 以键值对的形式返回,可用的api值true,不可用为false
//                      // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
//                      }
//                 });
                   //接口1:获取网络类型
                    wx.getNetworkType({
                        success: function (res) {
                          oldNet = res.networkType; // 返回网络类型2g,3g,4g,wifi
//                        alert("网络类型"+ oldNet);
                        }
                      });
                    // 拍照
//                  alert(document.querySelector('.head_portrait'));
                    document.querySelector('.head_portrait').onclick = function (){
                        
                        $("#tips").html("点击上传图片");
                        
                        var img1 = $('#chooseImage1');
                        //接口2:拍照或从手机相册中选图接口
                        wx.chooseImage({
                            count: 1, // 默认9
                            sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
                            sourceType: ['album', 'camera'],//可以指定来源是相册还是相机,默认二者都有
                            success: function (res) {
                                var imgLocalId = res.localIds;//返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
//                              alert("imgLocalId=" + imgLocalId);
//                              alert(res.contentType);
                                if(!imgLocalId){
                                    alert(2);
                                    fnPicInfo('',imgLocalId,'choose','fb',JSON.stringify(res));
                                }
                                img1.attr('src',imgLocalId);
                                
                                //选择图片之后询问是否确认上传
                                $("#isupload").css("display","block");
                                
                                //不上传或者重新选择
                                $("#isupload_n").click(function(){
                                    $("#isupload").css("display","none");
                                    $("#tips").html("重新选择");
                                    $("#chooseImage1").src("");
                                });
                                
                                //确认上传
                                $("#isupload_y").click(function(){
                                    
                                    $("#isupload").css("display","none");
                                    
                                    //接口3:上传图片接口
                                    wx.uploadImage({
                                        localId: imgLocalId[0], // 需要上传的图片的本地ID,由chooseImage接口获得
                                        isShowProgressTips: 1, // 默认为1,显示进度提示
                                        success: function (res) {
                                            if(res.serverId.indexOf("wxLocalResource://")>=0){
                                                mui.alert('',"图片上传失败,请重新上传!",'');
                                                return;
                                            }
                                            mediaId = res.serverId;
                                            if(!mediaId){
                                              fnPicInfo(mediaId,imgLocalId,'upload','fb',JSON.stringify(res));
                                            } 
                                            img1.attr('src',imgLocalId);
                                            mediaId1 = mediaId;
                                            localId1 = imgLocalId;
                                            //这里再写一个接口,将mediaId以及其他所需参数传到后台。回调函数中不需要写什么信息。
                                            
                                            //准备请求的参数:班级编码、mediaId、上传类型
                                                                                        //注:班级编码和上传类型是根据项目所需上传的参数,大家可根据自己的项目定义,但是mediaId肯定是要上传的。
                                            var requestdata = {     
                                                "classcode": classcode,
                                                "mediaId": mediaId,
                                                "uploadtype": uploadtype
                                            }
                                            alert(JSON.stringify(requestdata));
                                            //调用图片上传接口
                                            post_mediaId(requestdata);
                                        },
                                        fail: function(re){
                                          wx.getNetworkType({
                                          success: function (res) {
                                            $('.hidden_word1').show();
                                            newNet = res.networkType; // 返回网络类型2g,3g,4g,wifi
                                            fnPicInfo('','','upload','fb',re);
                                          }
                                        });
                                        }
                                    });
                                });
                            },
                          fail: function(re){
                            alert(JSON.stringify(re));
                            wx.getNetworkType({
                          success: function (res) {
                            $('.hidden_word1').show();
                            newNet = res.networkType; // 返回网络类型2g,3g,4g,wifi
                            fnPicInfo('','','choose','fb',re);
                          }
                        });
                          }
                        });
                    };
              })
              
             }
        });
          // 向后台数据库传递照片的相关信息,根据实际需求看是否需要传递这些信息。
//        function fnPicInfo(sId,lId,opType,businessType,remark) {
//          remark+="||"+oldNet+"||"+newNet;
//          $.ajax({
//              url:Url+'maintainCommon/addWXMediaRecord',
//              data:{
//                serviceId:sId,
//                localId:lId,
//                clientType:navigator.userAgent,
//                opType:opType,
//                businessType:businessType,
//                remark:remark
//              }
//          });
//        } 
    /********************获取微信配置数据结束********************** */
//向后端传递mediaId的值,以便其能到微信服务器上下载图片到本地服务器。
var post_mediaId = function(requestData){
    var server_IP = "服务器接口地址";  
    $.ajax({
        url: server_IP,
        type:"get",
        //params意为参数,是自定义的,用以表明这是传给后台的数据。
        data:{"params":JSON.stringify(requestData)},
        contentType:"application/json; charset=utf-8",
        //数据类型为jsonp,解决跨域问题。
        dataType:"jsonp",
        //自定义的jsonp回调函数名,默认为jQuery自动生成的随机函数
        jsonpCallback:"success_jsonpCallback_select",
        //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为callback)
        jsonp:"callbackparam",
        //访问成功时的回调函数
        success: function(respose){
            alert(respose.message);
        },
        error: function(data){
            alert("服务器连接失败");
        }
    });
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容