【原创】.Net 微信 JS-SDK图片、语音上传接口的实现(MVC)-(一 、上传图片)

前段时间在作一个微信的项目,遇到了一个上传图片的问题,花了一下午,解决了这个问题,而后把总结出来的代码,分享了出来。javascript

最近又有一个图片+语音的功能, 更是蛋疼, 本次采用的不是File文件上传,而后转码(Base64)的形式解决的,而是使用微信的开放Js-SDK实现的。php

咱们.net苦逼的很,微信官方的Demo上,有php、java、nodejs以及python的示例代码,就是没有咱们.NET的,不知道大神们是否是都藏私了,如今大的不出来,作小的出来顶!d=====( ̄▽ ̄*)b html

(开句玩笑话,别当真,鄙人菜鸟一枚)java

闲话不聊, 立刻进入正题node

首先,咱们看看官方给的 Js-SDK  https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CNpython

…… 文档相信你们已经不陌生了,如何配置才是问题, 接下来,给你们详解 微信Js-SDK的调用(顺带给你们介绍下使用,老手能够直接跳过前戏~ 1、2、3、四)web

 

 第一步: 绑定域名 ajax

域名是指安全回调的域名 , 首先打开属于你的公众号,数据库

点开 公众号设置 -  功能设置  - 设置安全回调域名json

如图: 

 

设置好安全回调的域名之后, 下面进入第二步

 

第二步: 引入JS-SDK文件 

官方已经给出了地址, 咱们直接在对应的页面中 引用这个JS便可, 这个JS里面的东西, 有微信已经封装好的交互(深究的话,鄙人暂时无能为力),直接引入便可

 

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>  相似这样的 

 

 

第三步: 经过config接口注入权限验证配置

从这个时候开始, 咱们就须要配置调用 JS-SDK里面的方法了;

 

全部须要使用JS-SDK的页面必须先注入配置信息,不然将没法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,因此使用pushState来实现web app的页面会致使签名失败,此问题会在Android6.2中修复)。

wx.config({

    debug: true, // 开启调试模式,调用的全部api的返回值会在客户端alert出来,若要查看传入的参数,能够在pc端打开,参数信息会经过log打出,仅在pc端时才会打印。

    appId: '', // 必填,公众号的惟一标识

    timestamp: , // 必填,生成签名的时间戳

    nonceStr: '', // 必填,生成签名的随机串

    signature: '',// 必填,签名,见附录1

    jsApiList: [] // 必填,须要使用的JS接口列表, 可参考官方的目录,添加之后,可使用该接口

});

下面是我在MVC里配置的代码附录

控制器端:

var appId = WeixinConfig.AppID;
            var nonceStr = Util.CreateNonce_str();
            var timestamp = Util.CreateTimestamp();
            var domain = System.Configuration.ConfigurationManager.AppSettings["Domain"];
            var url = domain + Request.Url.PathAndQuery;
            var jsTickect = WeixinConfig.TokenHelper.GetJSTickect();
            var string1 = "";
            var signature = JSAPI.GetSignature(jsTickect, nonceStr, timestamp, url, out string1);
            ViewBag.JSAPI = new JSSDKModel
            {
                appId = appId,
                nonceStr = nonceStr,
                signature = signature,
                timestamp = timestamp,
                string1 = string1,
            };

 

@VIew页面端:

 //配置微信
        wx.config({
            debug: false,
            appId: '@ViewBag.JSAPI.appId', // 必填,公众号的惟一标识
            timestamp: @ViewBag.JSAPI.timestamp, // 必填,生成签名的时间戳
            nonceStr: '@ViewBag.JSAPI.nonceStr', // 必填,生成签名的随机串
            signature: '@ViewBag.JSAPI.signature',// 必填,签名,见附录1
            jsApiList: [
              'chooseImage',
              'previewImage',
              'uploadImage',
              'downloadImage',
              'checkJsApi',
              'startRecord',
              'stopRecord',
              'onVoiceRecordEnd',
              'playVoice',
              'pauseVoice',
              'stopVoice',
              'onVoicePlayEnd',
              'uploadVoice',
              'downloadVoice',
              'getNetworkType'
            ]
        });

 

配置完成后,咱们进入第四步。

 

第四步: 接口验证

官方给的验证方法有 Ready 成功验证 和 Error 失败验证,下面咱们看看代码

 

wx.ready(function(){
    // config信息验证后会执行ready方法,全部接口调用都必须在config接口得到结果以后,config是一个客户端的异步操做,因此若是须要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则能够直接调用,不须要放在ready函数中。
});

wx.error(function(res){
    // config信息验证失败会执行error函数,如签名过时致使验证失败,具体错误信息能够打开config的debug模式查看,也能够在返回的res参数中查看,对于SPA能够在这里更新签名。
});

  

再看看官方的接口调用说明:

全部接口经过wx对象(也可以使用jWeixin对象)来调用,参数是一个对象,除了每一个接口自己须要传的参数以外,还有如下通用参数:

1.success:接口调用成功时执行的回调函数。

2.fail:接口调用失败时执行的回调函数。

3.complete:接口调用完成时执行的回调函数,不管成功或失败都会执行。

4.cancel:用户点击取消时的回调函数,仅部分有用户取消操做的api才会用到。

5.trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。

备注:不要尝试在trigger中使用ajax异步请求修改本次分享的内容,由于客户端分享操做是一个同步操做,这时候使用ajax的回包会尚未返回。

以上几个函数都带有一个参数,类型为对象,其中除了每一个接口自己返回的数据以外,还有一个通用属性errMsg,其值格式以下:

调用成功时:"xxx:ok" ,其中xxx为调用的接口名

用户取消时:"xxx:cancel",其中xxx为调用的接口名

调用失败时:其值为具体错误信息

 

了解了以上信息之后,接下来就能够进入咱们今天主要探讨的一个问题了——微信的图片接口和语音接口

 

咱们先看图片接口,而后一一实验

图像接口
拍照或从手机相册中选图接口
wx.chooseImage({
    count: 1, // 默认9
    sizeType: ['original', 'compressed'], // 能够指定是原图仍是压缩图,默认两者都有
    sourceType: ['album', 'camera'], // 能够指定来源是相册仍是相机,默认两者都有
    success: function (res) {
        var localIds = res.localIds; // 返回选定照片的本地ID列表,localId能够做为img标签的src属性显示图片
    }
});
预览图片接口
wx.previewImage({
    current: '', // 当前显示图片的http连接
    urls: [] // 须要预览的图片http连接列表
});
上传图片接口
wx.uploadImage({
    localId: '', // 须要上传的图片的本地ID,由chooseImage接口得到
    isShowProgressTips: 1, // 默认为1,显示进度提示
    success: function (res) {
        var serverId = res.serverId; // 返回图片的服务器端ID
    }
});
备注:上传图片有效期3天,可用微信多媒体接口下载图片到本身的服务器,此处得到的 serverId 即 media_id。
下载图片接口
wx.downloadImage({
    serverId: '', // 须要下载的图片的服务器端ID,由uploadImage接口得到
    isShowProgressTips: 1, // 默认为1,显示进度提示
    success: function (res) {
        var localId = res.localId; // 返回图片下载后的本地ID
    }
});

关于图片这边,微信官方提供了四大接口,分别是选择图片的接口, 这个选择相似于微信的图片选择,其实就是JS和微信的交互体验,

 

选择一个一个接口解释

选择图片接口
chooseImage

 :在选择好图片之后,图片有一个localId返回,这个localId是微信缓存本地的一个ID,能够直接使用这个localId,进行图片显示,

例如:  $("#img").append('<img src="'+localId+'" style="width:50px; height:50px;"/> <br />'); 这样的一句话,会在img标签里面,添加一张刚刚你选择的图片

预览图片接口
previewImage

:咱们注意到,这个预览图片的接口,有两个参数, 一个是 current ,一个 urls  , 这两个参数是什么意思呢? 首先, 不论是current 仍是 urls , 里面的属性值, 都是http:// 的 须要预览的图片的地址, current 表示在调用这个接口时

会显示在第一页的图片, 而urls是表示,显示的图片集合 , 例如 :

var imgList = [
                'http://h.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c70a6b76782d6277f9f2ff850.jpg',
            ];
            wx.previewImage({
                current: imgList[0],
                urls:  imgList
            });

  

这样,当点击的事件触发到这个方法后,会调用这个预览接口,实现微信端看到的,点小图, 看到大图的效果

 

上传图片接口
uploadImage

上传图片这个接口,不少人有这样的疑问(包括我第一次也是): 这个上传的图片在哪? 上传到哪儿了去了? 咱们怎么才能用这个图片?

接下来,我感同身受的,一个一个解决这个问题。

疑: 上传的图片在哪里? - 答 : 咱们注意到,以前在调用选择图片的接口的时候,有一个localId , 我解释过,是微信端缓存本地的一个图片编号,那么,咱们联想一下, 这个localId ,是否就是选择获得的localId了, 没有错, 就是这个localId, 那也就是说,

咱们想要使用上传接口, 首先, 咱们得选择图片,才能进行相应的上传操做。

疑: 上传到哪儿去了? - 答: 当存在这个localId的时候,接口会找到相对应的图片上,而后把该图片,经过另外一个接口 : https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE

上传至微信服务器的临时素材里面,固然,这个临时素材只有三天,而且有空间限制, 具体参考微信公众号里面的接口权限一栏 。

疑: 咱们怎么才能用这个图片? - 答: 当调用图片上传接口成功, 会有一个返回值返回给咱们 ,类型是这样的- {"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789} ,

咱们须要注意到的有用的信息 就是这个
media_id ,这个media_id 表示咱们所上传的素材, 在素材库里的位置, 当咱们想要使用它的时候, 只须要把这个 media_id 还有 token 请求到素材请求的地址, 就能够获得使用这个素材了。

下载图片接口
downloadImage

其实在上一个接口里面,稍稍已经提到过这个接口的使用, 没有错, 这个接口就是为了下载临时的素材,而后返回一个localId, 此时的localId, 是一个全新的, 表明的是下载到的图片的localId, 使用的方法也仍是很简单, 经过一个 Src 属性便可使用



讲到这里, 不得不停一下, 咱们彷佛忽略了些什么东西了,这些图片只能用三天,那三天后怎么办? 还有啊, 这个素材库有大小的限制, 不够了怎么办?
怎么办? 问我好咯, 我来分享一个办法—— 那就是转存到咱们的服务器上, 微信已经替咱们压缩了,咱们下载下来, 而后转一下,送到咱们本身的服务器上,留个地址,在咱们的数据库存储一下,
一张能够持久高清无码图, 就这样被咱们收入“囊中”。

下面继续贴代码, 看不懂的私聊,


  <a href="javascript:void(0);" onclick="javascript:chooseImage();">选择图片</a>
        <a href="javascript:void(0);" onclick="javascript:uploadImage();">图片上传</a>
        <a href="javascript:void(0);" onclick="javascript:downloadImage();">图片下载</a>
        <a href="javascript:void(0);" onclick="javascript:previewImage();">图片预览</a>
        <div id="img">选择的图片</div>
        <div id="img2"> 下载的图片</div>



<script type="text/javascript">
        wx.config({
            debug: false,
            appId: '@ViewBag.JSAPI.appId', // 必填,公众号的惟一标识
            timestamp: @ViewBag.JSAPI.timestamp, // 必填,生成签名的时间戳
            nonceStr: '@ViewBag.JSAPI.nonceStr', // 必填,生成签名的随机串
            signature: '@ViewBag.JSAPI.signature',// 必填,签名,见附录1
            jsApiList: [
              'chooseImage',
              'previewImage',
              'uploadImage',
              'downloadImage',
              'checkJsApi',
              'startRecord',
              'stopRecord',
              'onVoiceRecordEnd',
              'playVoice',
              'pauseVoice',
              'stopVoice',
              'onVoicePlayEnd',
              'uploadVoice',
              'downloadVoice',
              'getNetworkType'
            ]
        });

        wx.ready(function () {
            //返回网络类型
            wx.getNetworkType({
                success: function (res) {
                    var networkType = res.networkType; // 返回网络类型2g,3g,4g,wifi
                    jQuery(function() {
                        $('#networkType').html(networkType);
                    });
                }
            });
        });

        // 5.1 拍照、本地选图
        var images = {
            localId: [],
            serverId: []
        };

        function chooseImage() {
            wx.chooseImage({
                success: function (res) {
                    images.localId = res.localIds;
                    jQuery(function(){
                        $.each(res.localIds, function(i, n){
                            $("#img").append('<img src="'+n+'" style="width:50px; height:50px;"/> <br />');
                        });
                    });
                }
            });
        }

        // 5.2 图片预览
        function previewImage()
        {
            var imgList = [
                'http://h.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c70a6b76782d6277f9f2ff850.jpg',
            ];
            wx.previewImage({
                current: imgList[0],
                urls:  imgList
            });
        }

        // 5.3 上传图片
        var i = 0, length =0;
        function uploadImage(){
            if (images.localId.length == 0) {
                alert('请先使用选择图片按钮');
                return;
            }
            length= images.localId.length;
            upload();
        }

        function upload() {
            wx.uploadImage({
                localId: images.localId[i],
                success: function (res) {
                    i++;
                    //alert('已上传:' + i + '/' + length);
                    images.serverId.push(res.serverId);
                    $("#img2").append('<img src="'+res.localId+'"  style="width:50px; height:50px;"/ /> <br />');
                    downloadImage(res.serverId);
                    if (i < length) {
                        upload();
                    }
                },
                fail: function (res) {
                    alert(JSON.stringify(res));
                }
            });
        }

        //下载图片
        function downloadImage(serverId)
        {
            $.get("@Url.Action("WeixinDownloadImage","Home")",{mediaId:serverId},function(data){
                alert(data);
            },"json")
        }

        wx.error(function (res) {
            alert(res.errMsg);
        });

</script>

  

 

 

注意到,我有定义一个全局变量, 能够拓展到多图上传, 还有一个递归的上传。 我先回去了,下班了,回家烧饭吃。

 

服务器端的,和语音的,下次再聊。

相关文章
相关标签/搜索