前提・実現したいこと
ブラウザにAzure Blob Storage上にある画像(png)を表示させたいです。
(これはAzure SignalRを使ったリアルタイム画像表示を見据えた、その前段階の試作です。)
画像を表示させるときは、ブラウザからAzure Functions上のHTTPトリガーを起動し、そこで画像データを取得・Base64エンコードしてブラウザへ返却するようにしています。FunctionsのInput項目(Functionsの引数)としてBlob Storageを設定しているので、そこから画像データを取得することを考えています。
ブラウザでは、<img src="data:image/png;base64,xxx" />としてBase64エンコードしたものが表示されるようにしています。
発生している問題・エラーメッセージ
問題は、Functionsの引数から画像データを取得し、Base64エンコードできていないことです。
どうすればよいのか躓いている状態です。
気になっていることの1つは、Functionsに設定しているBlob Storageの引数の型が文字列(string)であることです(Functionsをjavascriptで記述している場合。)。
画像データなのでバイナリ(もしくはAzureのチュートリアルから考えてストリーム型)を想定していました。
該当のソースコード
Functionsのindex.js
javascript
1module.exports = async function (context, req, myInputBlob) { 2 context.log( 'type:' + typeof myInputBlob ); // "type:string" と出力される。 3 const responseMessage = Buffer.from( myInputBlob, 'utf-8' ).toString('base64'); // Base64エンコードできない。期待:iVBORw0KGg..... 4 5 context.res = { 6 // status: 200, /* Defaults to 200 */ 7 body: responseMessage 8 }; 9}
Functionsのfunction.json
json
1{ 2 "bindings": [ 3 { 4 "authLevel": "anonymous", 5 "type": "httpTrigger", 6 "direction": "in", 7 "name": "req", 8 "methods": [ 9 "get", 10 "post" 11 ] 12 }, 13 { 14 "type": "http", 15 "direction": "out", 16 "name": "res" 17 }, 18 { 19 "name": "myInputBlob", 20 "type": "blob", 21 "path": "my-file-system/test_file.png", 22 "connection": "AzureWebJobsStorage", 23 "direction": "in" 24 } 25 ] 26}
クライアント(Vue.js)HTML Body部のみ
index.html
html
1 <div id="app" class="container"> 2 <h1 class="title">Image</h1> 3 <img :src="responseMessages" /> 4 <!-- <p>{{ responseMessages }}</p> --> 5 </div> 6 7 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js" integrity="sha256-chlNFSVx3TdcQ2Xlw7SvnbLAavAQLO0Y/LBiWX04viY=" crossorigin="anonymous"></script> 8 <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js" integrity="sha256-S1J4GVHHDMiirir9qsXWc8ZWw74PHHafpsHp5PXtjTs=" crossorigin="anonymous"></script> 9 <script src="index.html.js" type="text/javascript"></script>
クライアント (Vue.js)
index.html.js
javascript
1const LOCAL_BASE_URL = 'http://localhost:7071'; 2const REMOTE_BASE_URL = '<FUNCTION_APP_ENDPOINT>'; // 変更不要 3const IMAGE_BASE64 = 'data:image/png;base64,'; 4 5const getAPIBaseUrl = () => { 6 const isLocal = /localhost/.test(window.location.href); 7 return isLocal ? LOCAL_BASE_URL : REMOTE_BASE_URL; 8} 9 10const app = new Vue({ 11 el: '#app', 12 data() { 13 return { 14 stocks: [], 15 responseMessages: IMAGE_BASE64 16 } 17 }, 18 methods: { 19 async getStocks() { 20 try { 21 const apiUrl = `${getAPIBaseUrl()}/api/getImageBase64`; 22 const response = await axios.get(apiUrl); 23 app.responseMessages = IMAGE_BASE64 + response.data; 24 // console.log( `message:${response.data}` ); 25 } catch (ex) { 26 console.error(ex); 27 } 28 } 29 }, 30 created() { 31 this.getStocks(); 32 } 33});
bs-config.json
javascript
1{ 2 "port": 8080, 3 "files": ["./public/**/*.{html,htm,css,js}"], 4 "server": { "baseDir": "./public" } 5}
package.json
javascript
1{ 2 "name": "testgetimagebyfunctions", 3 "version": "1.0.0", 4 "description": "", 5 "scripts": { 6 "start": "lite-server --baseDir=\"public\"", 7 "test": "echo \"No tests yet...\"" 8 }, 9 "dependencies": {}, 10 "devDependencies": { 11 "lite-server": "^2.5.3" 12 } 13}
local.settings.json
json
1{ 2 "IsEncrypted": false, 3 "Values": { 4 "AzureWebJobsStorage": "xxx", 5 "FUNCTIONS_WORKER_RUNTIME": "node" 6 }, 7 "Host" : { 8 "LocalHttpPort": 7071, 9 "CORS": "http://localhost:8080", 10 "CORSCredentials": true 11 } 12}
AzureWebJobsStorageは各自で接続文字列を設定ください。
試したこと
- Functionsの引数に設定されている変数(myInputBlob)を使わずに、接続文字列など必要な処理を記述してBlob Storageにアクセスし、Base64エンコードした結果を返すと、ブラウザに画像表示できました。
- 変数のmyInputBlobの型がstringであったので、そのままデバッグ出力してみると、”?PNG...”のように出力(文字化けあり)されるため、画像データは取得できている?。
- FunctionsをjavascriptからPythonに変更して試しても、同じようにブラウザに画像表示できなかった。ただ、myInputBlobの型はstringではなく、azure.functions.InputStream型でした。
補足情報(FW/ツールのバージョンなど)
ローカル環境
- Windows10 Pro
- Node.js v12.18.1
- Visual Studio Code 1.47.2
- Azure Functions 2.7.2628
クラウド
- Azure ストレージアカウント StorageV2 (汎用 v2)
あなたの回答
tips
プレビュー