質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.93%

Azure Functions(HTTPトリガー)で取得したBlob Storage上の画像をブラウザに表示させたい。

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 245

NagaseTomohiko

score 11

前提・実現したいこと

ブラウザに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

module.exports = async function (context, req, myInputBlob) {
    context.log( 'type:' + typeof myInputBlob );  // "type:string" と出力される。
    const responseMessage = Buffer.from( myInputBlob, 'utf-8' ).toString('base64'); // Base64エンコードできない。期待:iVBORw0KGg.....

    context.res = {
        // status: 200, /* Defaults to 200 */
        body: responseMessage
    };
}

Functionsのfunction.json

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "name": "myInputBlob",
      "type": "blob",
      "path": "my-file-system/test_file.png",
      "connection": "AzureWebJobsStorage",
      "direction": "in"
    }
  ]
}

クライアント(Vue.js)HTML Body部のみ
index.html

   <div id="app" class="container">
        <h1 class="title">Image</h1>
        <img :src="responseMessages" />
        <!-- <p>{{ responseMessages }}</p> -->
   </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js" integrity="sha256-chlNFSVx3TdcQ2Xlw7SvnbLAavAQLO0Y/LBiWX04viY=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js" integrity="sha256-S1J4GVHHDMiirir9qsXWc8ZWw74PHHafpsHp5PXtjTs=" crossorigin="anonymous"></script>
    <script src="index.html.js" type="text/javascript"></script>

クライアント (Vue.js)
index.html.js

const LOCAL_BASE_URL = 'http://localhost:7071';
const REMOTE_BASE_URL = '<FUNCTION_APP_ENDPOINT>';  // 変更不要
const IMAGE_BASE64 = 'data:image/png;base64,';

const getAPIBaseUrl = () => {
    const isLocal = /localhost/.test(window.location.href);
    return isLocal ? LOCAL_BASE_URL : REMOTE_BASE_URL;
}

const app = new Vue({
    el: '#app',
    data() {
        return {
            stocks: [],
            responseMessages: IMAGE_BASE64
        }
    },
    methods: {
        async getStocks() {
            try {
                const apiUrl = `${getAPIBaseUrl()}/api/getImageBase64`;
                const response = await axios.get(apiUrl);
                app.responseMessages = IMAGE_BASE64 + response.data;
                // console.log( `message:${response.data}` );
            } catch (ex) {
                console.error(ex);
            }
        }
    },
    created() {
        this.getStocks();
    }
});


bs-config.json

{
  "port": 8080,
  "files": ["./public/**/*.{html,htm,css,js}"],
  "server": { "baseDir": "./public" }
}


package.json

{
  "name": "testgetimagebyfunctions",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "lite-server --baseDir=\"public\"",
    "test": "echo \"No tests yet...\""
  },
  "dependencies": {},
  "devDependencies": {
    "lite-server": "^2.5.3"
  }
}


local.settings.json

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "xxx",
    "FUNCTIONS_WORKER_RUNTIME": "node"
  },
  "Host" : {
    "LocalHttpPort": 7071,
    "CORS": "http://localhost:8080",
    "CORSCredentials": true
  }
}


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)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る