1. 程式人生 > >MVC 微信公眾號js-sdk上傳圖片至自己伺服器

MVC 微信公眾號js-sdk上傳圖片至自己伺服器

微信JS-SDK圖片介面呼叫

本篇將使用.NET MVC介紹微信上傳圖片至自己伺服器

微信公眾平臺js-sdk官方說明文件:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

通過文件中微信JS-SDK的概述和JSSDK使用步驟,我們可以瞭解到微信提供給我們的介面是如何使用的。

影象介面

拍照或從手機相簿中選圖介面

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。

注意到微信只提供給我們上傳圖片後的ServerId,而已有效期只有3天,所以我們需要將臨時素材上傳至自己伺服器中,serverId即為獲取臨時素材的MEDIA_ID

請求獲取臨時素材的介面地址為:

"https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID"

現在直接前臺程式碼

@model Senparc.Weixin.MP.Helpers.JsSdkUiPackage
@{
    ViewBag.Title = "微信圖片介面Demo";
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>微信圖片介面Demo</title>
    <!--jQuery非JS-SDK必須-->
    <script src="~/scripts/jquery-1.10.2.min.js"></script>
    <script src="@(Request.Url.Scheme)://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    <style type="text/css">
        button {
            width: 100px;
            height: auto;
            display: block;
            margin-bottom: 5px;
            font-size: 20px;
        }
    </style>
</head>
<body>
    <div>
        <button onclick="chooseImage();">選擇圖片</button>
        <button onclick="uploadImage();">圖片上傳</button>
        <button onclick="previewImage();">圖片預覽</button>
        選擇的圖片<div id="img"></div>
        上傳的圖片<div id="img2"></div>
    </div>

    <script type="text/javascript">
        wx.config({
            debug: false, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
            appId: '@Model.AppId', // 必填,公眾號的唯一標識
            timestamp: '@Model.Timestamp', // 必填,生成簽名的時間戳
            nonceStr: '@Model.NonceStr', // 必填,生成簽名的隨機串
            signature: '@Model.Signature',// 必填,簽名
            jsApiList: [
                    'chooseImage',
                    'previewImage',
                    'uploadImage'
            ]
        });
        // 全域性變數儲存
        var images = {
            localIds: [],
            serverIds: []
        };
        //1.拍照、本地選圖
        function chooseImage() {
            if (images.localIds.length == 9) {
                alert('最多允許選中9張圖片');
                return;
            }
            else {
                wx.chooseImage({
                    count: 9 - images.localIds.length, // 預設9
                    sizeType: ['original', 'compressed'], // 可以指定是原圖還是壓縮圖,預設二者都有
                    sourceType: ['album', 'camera'], // 可以指定來源是相簿還是相機,預設二者都有
                    success: function (res) {
                        $(function () {
                            $.each(res.localIds, function (i, n) {
                                images.localIds.push(n);
                                $("#img").append('<img src="' + n + '" style="width:70px; height:70px;margin-right:5px;"/>');
                            });
                        });
                    },
                    cancel: function () {
                        alert("已取消選擇");
                    }
                });
            }
        }
        //2.上傳圖片
        var i = 0, length = 0;
        function uploadImage() {
            i = 0;
            length = 0;
            if (images.localIds.length == 0) {
                alert('請先使用選擇圖片按鈕');
                return;
            }
            length = images.localIds.length;
            upload();
        }
        //遞迴呼叫的方法
        function upload() {
            wx.uploadImage({
                localId: images.localIds[i].toString(),
                success: function (res) {
                    images.serverIds.push(res.serverId.toString());
                },
                fail: function (res) {
                    alert(JSON.stringify(res));
                },
                complete: function (res) {
                    i++;
                    if (i < length) {
                        upload();
                    }
                    if (i == length) {
                        downloadImage(images.serverIds);
                    }
                }
            });
        }
        //下載圖片的方法
        function downloadImage(serverIds) {
            $.get('@Url.Action("DownloadImageAsync")', { mediaArray: JSON.stringify(serverIds) }, function (data) {
                $.each(data, function (i, n) {
                    $("#img2").append('<img src="' + n + '" style="width:70px; height:70px;margin-right:5px;"/>');
                });
                //清空images
                images = {
                    localIds: [],
                    serverIds: []
                };
            }, "json");
        }

        //3.圖片預覽
        function previewImage() {
            var imgList = [
                  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1516438929475&di=b957eeb994395ff6b99ad5a2aa0330f3&imgtype=0&src=http%3A%2F%2Fimg1.3lian.com%2Fimg013%2Fv4%2F11%2Fd%2F64.jpg',
                  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1516438929477&di=ca86274989d88b420edf367a3f5c4ff3&imgtype=0&src=http%3A%2F%2Fimg2.3lian.com%2F2014%2Ff4%2F209%2Fd%2F23.jpg',
                  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1516438929476&di=bb23036f8232b23f11d7f7226d91ca22&imgtype=0&src=http%3A%2F%2Fnews.shangqiuw.com%2Fupload%2FNews%2F2016-10-14%2F20161014111158277f960f.jpg'
            ];
            wx.previewImage({
                current: imgList[0],
                urls: imgList
            });
        }
        wx.error(function (res) {
            alert(res.errMsg);
        });
    </script>
</body>
</html>

接下來看控制器的程式碼

using Senparc.CO2NET.Extensions;
using Senparc.Weixin.MP.Helpers;
using System;
using System.Web.Mvc;
using Newtonsoft.Json;
using System.IO;
namespace WebSample.Controllers
{
    using Service;
    using System.Drawing;
    using System.Net.Http;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    public class WeixinJSSDKController : Controller
    {
        //
        // GET: /WeixinJSSDK/
        public ActionResult Index()
        {
            //盛派開源封裝的JSSDKHelper類,傳遞:AppId,Timestamp,NonceStr,Signature
            var jssdkUiPackage = JSSDKHelper.GetJsSdkUiPackage(Config.AppId, Config.AppSecret, Request.Url.AbsoluteUri);
            return View(jssdkUiPackage);
        }

        #region 上傳圖片下載至自己伺服器的方法(非同步請求)
        /// <summary>
        /// 上傳圖片下載至自己伺服器的方法(非同步請求)
        /// </summary>
        /// <param name="mediaArray"></param>
        /// <returns></returns>
        [HttpGet]
        public ActionResult DownloadImage(string mediaArray)
        {
            List<string> result = new List<string>();
            try
            {
                var mediaIdList = JsonConvert.DeserializeObject<List<string>>(mediaArray);
                string ip_port = Request.Url.Authority;
                foreach (var mediaId in mediaIdList)
                {
                    string path = string.Format("/upload/UploadImage/{0}/", DateTime.Now.ToString("yyyy-MM-dd"));
                    string fileName = Guid.NewGuid().ToString("n") + ".jpg";
                    string mapPath = Server.MapPath(path);
                    var dir = mapPath + fileName;
                    if (!Directory.Exists(mapPath))
                    {
                        Directory.CreateDirectory(mapPath);
                    }
                    using (MemoryStream ms = new MemoryStream())
                    {
                        //關鍵程式碼,senparc已經封裝好了,這裡使用的是media介面
                        Senparc.Weixin.MP.AdvancedAPIs.MediaApi.Get(Config.AppId, mediaId, ms);
                        using (FileStream fs = new FileStream(dir, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                        {
                            ms.Position = 0;
                            byte[] buffer = new byte[5 * 1024 * 1024];
                            int bytesRead = 0;
                            while ((bytesRead = ms.Read(buffer, 0, buffer.Length)) != 0)
                            {
                                fs.Write(buffer, 0, bytesRead);
                            }
                            fs.Flush();
                        }
                        result.Add("https://" + ip_port + path + fileName);
                    }
                }
            }
            catch (Exception ex)
            {
                Senparc.Weixin.WeixinTrace.SendCustomLog("發生錯誤了", ex.Message);
            }
            return Json(result, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 上傳圖片下載至自己伺服器的方法(非同步請求)
        /// </summary>
        /// <param name="mediaArray"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ActionResult> DownloadImageAsync(string mediaArray)
        {
            List<string> result = new List<string>();
            try
            {
                var mediaIdList = JsonConvert.DeserializeObject<List<string>>(mediaArray);
                string ip_port = Request.Url.Authority;
                foreach (var mediaId in mediaIdList)
                {
                    string path = string.Format("/upload/UploadImage/{0}/", DateTime.Now.ToString("yyyy-MM-dd"));
                    string fileName = Guid.NewGuid().ToString("n") + ".jpg";
                    string mapPath = Server.MapPath(path);
                    var dir = mapPath + fileName;
                    if (!Directory.Exists(mapPath))
                    {
                        Directory.CreateDirectory(mapPath);
                    }
                    using (MemoryStream ms = new MemoryStream())
                    {
                        await Senparc.Weixin.MP.AdvancedAPIs.MediaApi.GetAsync(Config.AppId, mediaId, ms);
                        using (FileStream fs = new FileStream(dir, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                        {
                            ms.Position = 0;
                            byte[] buffer = new byte[5 * 1024 * 1024];
                            int bytesRead = 0;
                            while ((bytesRead = ms.Read(buffer, 0, buffer.Length)) != 0)
                            {
                                fs.Write(buffer, 0, bytesRead);
                            }
                            fs.Flush();
                        }
                        result.Add("https://" + ip_port + path + fileName);
                    }
                }
            }
            catch (Exception ex)
            {
                Senparc.Weixin.WeixinTrace.SendCustomLog("發生錯誤了", ex.Message);
            }
            return Json(result, JsonRequestBehavior.AllowGet);
        }

        #endregion

    }
}

效果圖為: