摘要:最近在做微信公眾號(hào),需要將圖片上傳至阿里云。利用模塊將圖片寫(xiě)到內(nèi)存微信多媒體文件文件路徑圖片上傳阿里云結(jié)果上傳文件出錯(cuò)這種方式將圖片暫存在內(nèi)存里面,那如果并發(fā)量很大,是不是內(nèi)存要爆炸了都感覺(jué)還是不可取。
最近在做微信公眾號(hào),需要將圖片上傳至阿里云OSS。在做這個(gè)功能的過(guò)程中,我走了不少?gòu)澛罚瑖L試過(guò)很多種方法,最后終于研究出一種便捷優(yōu)美的方式。現(xiàn)在把這些方法和思路記錄下來(lái),避免遺忘。
一、通過(guò)瀏覽器直接傳給OSS這種方式最簡(jiǎn)單。因?yàn)槲⑿殴娞?hào)的跳轉(zhuǎn)頁(yè)面是基于QQ瀏覽器的,所以可以直接使用HTML的input元素選擇圖片。
OSS有一個(gè)Post Object的接口允許HTML表單上傳文件,除了文件(file)之外,還有一些其他的字段如保存到OSS的路徑(key)、策略(policy)、自己的OSS應(yīng)用的accessKeyId、簽名(signature)等。
所以需要構(gòu)造表單。一般有兩種方式:
1)構(gòu)造DOM節(jié)點(diǎn),表單提交上傳像下面代碼這樣構(gòu)造form元素,然后利用$("form").submit()提交。
2)利用Html5的FormData對(duì)象上傳
像下面這樣構(gòu)造FormData對(duì)象,再通過(guò)ajax或fetch post表單數(shù)據(jù)。
const formData = new FormData(); formData.append("key", filePath); // OSS的保存路徑 formData.append("policy", policy); // 策略 formData.append("OSSAccessKeyId", accessKeyId); // OSS對(duì)象的標(biāo)識(shí) formData.append("success_action_status", "200"); // 成功返回碼 formData.append("signature", signature); // 簽名 formData.append("file", file); // 圖片文件,$("input[name="pic"]").files[0]二、服務(wù)端下載微信圖片再轉(zhuǎn)存至OSS
上面的方法雖然簡(jiǎn)單直接,但只能從相冊(cè)中選擇圖片,而想要拍攝圖片并上傳,則必須通過(guò)微信JS-SDK來(lái)調(diào)用相機(jī)。
wx.chooseImage({ count: 1, // 默認(rèn)9 sizeType: ["original", "compressed"], // 可以指定是原圖還是壓縮圖,默認(rèn)二者都有 sourceType: ["album", "camera"], // 可以指定來(lái)源是相冊(cè)還是相機(jī),默認(rèn)二者都有 success: function (res) { // 返回選定照片的本地ID列表,localId可以作為img標(biāo)簽的src屬性顯示圖片 var localIds = res.localIds; } });
這里有個(gè)問(wèn)題,微信JS-SDK選擇圖片之后返回的是圖片的標(biāo)識(shí)id,而不是實(shí)際的圖片文件,所以不能構(gòu)造form表單上傳OSS。
那該怎么辦呢?思路:將圖片先上傳至微信的服務(wù)器(最多保存3天),再通過(guò)微信的下載多媒體文件接口(http://file.api.weixin.qq.com...)將圖片下載到服務(wù)器,再上傳至OSS(雖然有點(diǎn)繞,但可行)。
客戶(hù)端代碼:
wx.chooseImage({ count: 1, // 默認(rèn)9 sizeType: ["original", "compressed"], sourceType: ["album", "camera"], success: function (res) { var localIds = res.localIds; wx.uploadImage({ localId: localIds[0], // 需要上傳的圖片的本地ID,由chooseImage接口獲得 isShowProgressTips: 1, // 默認(rèn)為1,顯示進(jìn)度提示 success: function (res) { var serverId = res.serverId; // 返回圖片的服務(wù)器端ID // do something ... // 調(diào)用自己搭建的服務(wù)端的api,傳入serverId,做獲取微信圖片上傳OSS的相關(guān)操作 doSomething(); } }); } });
小tips:選擇圖片時(shí)只要選擇了compressed,微信就會(huì)自動(dòng)幫我們壓縮圖片,官方文檔也說(shuō)明上傳的多媒體文件會(huì)控制格式和大小,其中圖片控制在jpg格式和1M以下的大小。所以,基本不用考慮圖片過(guò)大的問(wèn)題。實(shí)測(cè)中,8M的圖片壓縮后只有120KB左右。
服務(wù)端的代碼經(jīng)過(guò)了3次的演變才完善:
1)利用fs將圖片寫(xiě)到本地const fs = require("fs"); const request = require("require"); const OSS = require("ali-oss").Wrapper; const ossClient = new OSS({ accessKeyId: "your access key", accessKeySecret: "your access secret", bucket: "your bucket name", region: "oss-cn-hangzhou" }); // 需要獲取微信accessToken,這里不細(xì)說(shuō) const accessToken = "access token"; const mediaId = "xxxxxxx"; // 微信多媒體文件id const destPath = `weixin/images/201702/${mediaId}.jpg`; // OSS文件路徑,按自己喜歡構(gòu)造咯 const wxReq = request(`http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=${accessToken }&media_id=${mediaId}`); // 將文件流pipe到本地文件 wxReq.pipe(fs.createWriteStream(`${mediaId}.jpg`)); wxReq.on("end", () => { co(function* () { const result = yield ossClient.putStream(destPath, fs.createReadStream(`${mediaId}.jpg`), {timeout: 30 * 60 * 1000}); console.log("圖片上傳阿里云結(jié)果", result); fs.unlink(`${mediaId}.jpg`); // res.status(200).json(result); }).catch(err => { console.warn(err); //res.status(500).send("上傳文件出錯(cuò)"); }); });
這種方式需要頻繁地寫(xiě)文件和刪文件,感覺(jué)一點(diǎn)都不極客。
2)利用memory-streams模塊將圖片寫(xiě)到內(nèi)存const request = require("require"); const OSS = require("ali-oss").Wrapper; const streams = require("memory-streams"); const ossClient = new OSS({ accessKeyId: "your access key", accessKeySecret: "your access secret", bucket: "your bucket name", region: "oss-cn-hangzhou" }); const accessToken = "access token"; const mediaId = "xxxxxxx"; // 微信多媒體文件id const destPath = `weixin/images/201702/${mediaId}.jpg`; // OSS文件路徑 const writer = new streams.WritableStream(); const wxReq = request(`http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=${accessToken }&media_id=${mediaId}`); wxReq.pipe(writer); wxReq.on("end", () => { co(function* () { const result = yield ossClient.put(destPath, writer.toBuffer(), {timeout: 30 * 60 * 1000}); console.log("圖片上傳阿里云結(jié)果", result); // res.status(200).json(result); }).catch(err => { console.warn(err); //res.status(500).send("上傳文件出錯(cuò)"); }); });
這種方式將圖片暫存在內(nèi)存里面,那如果并發(fā)量很大,是不是內(nèi)存要爆炸了都?感覺(jué)還是不可取。
3)將下載圖片的流直接寫(xiě)入OSS文件折騰了好久,發(fā)現(xiàn)原來(lái)可以這么簡(jiǎn)單和優(yōu)雅:
const request = require("require"); const OSS = require("ali-oss").Wrapper; const ossClient = new OSS({ accessKeyId: "your access key", accessKeySecret: "your access secret", bucket: "your bucket name", region: "oss-cn-hangzhou" }); const accessToken = "access token"; const mediaId = "xxxxxxx"; // 微信多媒體文件id const destPath = `weixin/images/201702/${mediaId}.jpg`; // OSS文件路徑 const wxReq = request(`http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=${accessToken }&media_id=${mediaId}`); wxReq.on("response", (response) => { // request的響應(yīng)結(jié)果response可以作為讀取流傳給ossClient co(function* () { const result = yield ossClient.putStream(destPath, response, {timeout: 30 * 60 * 1000}); console.log("圖片上傳阿里云結(jié)果", result); // res.status(200).json(result); }).catch(err => { console.warn(err); //res.status(500).send("上傳文件出錯(cuò)"); }); });
這種方式省去了前面兩種方式的中間步驟,更加簡(jiǎn)練直接,個(gè)人認(rèn)為是最好的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/81513.html
摘要:一準(zhǔn)備工作開(kāi)通阿里云服務(wù),從控制臺(tái)上獲取和。參考資料阿里云官方文檔開(kāi)始使用阿里云官方文檔介紹如何在中快速使用訪問(wèn)服務(wù)微信公眾號(hào)圖片上傳至阿里云前端圖片直傳試驗(yàn)如何基于和,快速搭建音視頻文件上傳服務(wù)聲明轉(zhuǎn)發(fā)請(qǐng)注明出處,謝謝 一、準(zhǔn)備工作 1. 開(kāi)通阿里云OSS服務(wù),從控制臺(tái)上獲取AccessKeyId和AccessKeySecret。 2. 創(chuàng)建Bucket,并登錄OSS控制臺(tái) 3. 配...
摘要:筆主很早就開(kāi)始用阿里云存儲(chǔ)服務(wù)當(dāng)做自己的圖床了。阿里云對(duì)象存儲(chǔ)文檔,本篇文章會(huì)介紹到整合阿里云存儲(chǔ)服務(wù)實(shí)現(xiàn)文件上傳下載以及簡(jiǎn)單的查看。 Github 地址:https://github.com/Snailclimb/springboot-integration-examples(SpringBoot和其他常用技術(shù)的整合,可能是你遇到的講解最詳細(xì)的學(xué)習(xí)案例,力爭(zhēng)新手也能看懂并且能夠在看完...
摘要:接下來(lái)講解一下博客中用的圖床阿里云對(duì)象存儲(chǔ),簡(jiǎn)稱(chēng),雖然目前大家用的比較多的是七牛云之類(lèi)的,但是因?yàn)槲覀€(gè)人原因我還是選擇了阿里云,后面我會(huì)簡(jiǎn)單說(shuō)明下原因。 showImg(https://segmentfault.com/img/remote/1460000008838754?w=960&h=300); 前言 之前打算寫(xiě)一篇有關(guān)個(gè)人博客SEO優(yōu)化的體驗(yàn)和一些自身體會(huì),但是發(fā)現(xiàn)自己還沒(méi)完全...
閱讀 4312·2021-09-24 09:47
閱讀 1189·2021-09-03 10:33
閱讀 2071·2019-08-30 11:13
閱讀 1037·2019-08-30 10:49
閱讀 1759·2019-08-29 16:13
閱讀 2050·2019-08-29 11:28
閱讀 3097·2019-08-26 13:31
閱讀 3637·2019-08-23 17:14