WeChat公衆番号の画像をアリクラウドOSSにアップロードします.
6490 ワード
最近はWeChat公式アカウントを作っていますが、画像をアリクラウドOSSにアップロードする必要があります.この機能をする過程で、いろいろな回り道をして、いろいろな方法を試しました.今はこれらの方法と考え方を記録して、忘れないようにします.
一、ブラウザで直接OSSに伝える
この方法が一番簡単です.WeChat公衆番号のジャンプページはQQブラウザに基づいているので、直接HTMLの
フォームの作成が必要です.一般的に2つの方法があります.
1)DOMノードを作成し、フォームをアップロードします.
以下のコードのようにform要素を構成し、
以下のようにFormDataオブジェクトを構築し、ajaxまたはfetch postフォームデータを通過します.
上記の方法は簡単で直接ですが、写真はアルバムからしか選択できません.写真を撮ってアップロードするには、微信JS-SDKを通じてカメラを呼び出す必要があります.
どうすればいいですか?構想:画像を先にWeChatのサーバー(最大3日間保存)にアップロードして、微信のダウンロードマルチメディアファイルインターフェース(http://file.api.weixin.qq.com...)画像をサーバーにダウンロードし、OSSにアップロードします.
クライアントコード:
サービスのコードは3回の進化を経て改善されました.
1)fsを利用して写真をローカルに書く
2)memory-streamsモジュールを利用して画像をメモリに書き込みます.
3)ダウンロードした画像のストリームを直接OSSファイルに書き込みます.
長い間苦労しましたが、こんなに簡単で優雅なことができると分かりました.
一、ブラウザで直接OSSに伝える
この方法が一番簡単です.WeChat公衆番号のジャンプページはQQブラウザに基づいているので、直接HTMLの
input
要素を使って画像を選択することができます.
OSSにはPost Objectというインターフェースがあります.ファイル以外にもOSSに保存するパス、ポリシー、自分のOSSアプリケーションのaccessKeyId、署名などの他のフィールドがあります.フォームの作成が必要です.一般的に2つの方法があります.
1)DOMノードを作成し、フォームをアップロードします.
以下のコードのようにform要素を構成し、
$('form').submit()
を利用して提出します.
2)Html 5のFormDataオブジェクトを使ってアップロードする以下のようにFormDataオブジェクトを構築し、ajaxまたはfetch postフォームデータを通過します.
const formData = new FormData();
formData.append('key', filePath); // OSS
formData.append('policy', policy); //
formData.append('OSSAccessKeyId', accessKeyId); // OSS
formData.append('success_action_status', '200'); //
formData.append('signature', signature); //
formData.append('file', file); // ,$('input[name="pic"]').files[0]
二、サービス端末でWeChatの画像をダウンロードしてからOSSに保存する.上記の方法は簡単で直接ですが、写真はアルバムからしか選択できません.写真を撮ってアップロードするには、微信JS-SDKを通じてカメラを呼び出す必要があります.
wx.chooseImage({
count: 1, // 9
sizeType: ['original', 'compressed'], // ,
sourceType: ['album', 'camera'], // ,
success: function (res) {
// ID ,localId img src
var localIds = res.localIds;
}
});
ここで問題がありますが、WeChat JS-SDKは画像を選択して戻ってくるのは、実際の画像ファイルではなく、実際の画像ファイルなので、フォームを作成してOSSをアップロードすることができません.どうすればいいですか?構想:画像を先にWeChatのサーバー(最大3日間保存)にアップロードして、微信のダウンロードマルチメディアファイルインターフェース(http://file.api.weixin.qq.com...)画像をサーバーにダウンロードし、OSSにアップロードします.
クライアントコード:
wx.chooseImage({
count: 1, // 9
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: function (res) {
var localIds = res.localIds;
wx.uploadImage({
localId: localIds[0], // ID, chooseImage
isShowProgressTips: 1, // 1,
success: function (res) {
var serverId = res.serverId; // ID
// do something ...
// api, serverId, OSS
doSomething();
}
});
}
});
小tips:画像を選ぶ時はcompressed
を選択すると、WeChatが自動的に画像を圧縮してくれます.公式文書もアップロードされたマルチメディアファイルがフォーマットとサイズを制御すると説明しています.画像はjpg形式と1 M以下のサイズに制御されます.ですから、写真の大きさはあまり考えなくてもいいです.実測では、8 Mの画像を圧縮した後は120 KBぐらいです.サービスのコードは3回の進化を経て改善されました.
1)fsを利用して写真をローカルに書く
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,
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}`);
// 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(' ', result);
fs.unlink(`${mediaId}.jpg`);
// res.status(200).json(result);
}).catch(err => {
console.warn(err);
//res.status(500).send(' ');
});
});
このような方式は頻繁にファイルを書く必要があります.2)memory-streamsモジュールを利用して画像をメモリに書き込みます.
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(' ', result);
// res.status(200).json(result);
}).catch(err => {
console.warn(err);
//res.status(500).send(' ');
});
});
このように写真をメモリに保存します.もし合併量が大きいなら、メモリが爆発してもいいですか?感じはやはり取るべきでないです.3)ダウンロードした画像のストリームを直接OSSファイルに書き込みます.
長い間苦労しましたが、こんなに簡単で優雅なことができると分かりました.
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 response ossClient
co(function* () {
const result = yield ossClient.putStream(destPath, response, {timeout: 30 * 60 * 1000});
console.log(' ', result);
// res.status(200).json(result);
}).catch(err => {
console.warn(err);
//res.status(500).send(' ');
});
});
この方法は前の二つの方法の中間ステップを省き、もっと簡潔で直接的で、個人的には一番いいと思います.