Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

画像をJavaScriptでXHR経由で読み込む方法

スポンサードリンク

f:id:fa11enprince:20201111022041j:plain
やむをえない事情があり、JWT認証を通過して画像を表示させる必要があったので、
XHR(Ajax)で画像を読み込む方法を調べました。
同一ドメインならこんな苦労はしないのにーとか最近そんなことを悩んでいます。

サーバーサイドのコード

何でもいいのですが、最近お気に入りのexpress
サクッとなんか書くのが楽なんです。環境構築も長楽だし。
JavaScriptいいお。
Nodeはversion 12くらい。Expressはversion 4です。

$ express --view=ejs myapp

とかでサクッとひな形作って、
とりあえずroutes/image.jsとかいうルーターを作り、単にバイナリデータを返します。

const express = require('express');
const router = express.Router();
const fs = require('fs');

router.get('/', async (req, res, next) => {
    fs.readFile('./public/images/nyam.jpg', (err, data) => {
        if (err) {
            console.error(err);
            res.sendStatus(500);
            return;
        }
        res.writeHead(200, {'Content-Type': 'image/jpg'});
        res.end(data);
    });
});

module.exports = router;

index.jsのコードは省きます。
nyam.jpgというのは猫の画像です。にゃーむ。
当然PythonのFlaskでもRuby On Railsでもなんでもええです。楽なやつにしましょう。
Spring Bootでもいいですが若干だるいと思います。

フロントエンドのコード

jQueryでも実はできるとのことですが、まぁXHRでいいでしょう。 Blobってのを使うと超絶らくちんです。
Base64ならなんでもできるぜい、っていう素敵なおっさんから話は聞いてましたけど
めんどっちいんでBlobで。

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
    <div style='height: 300px;'>
      <img id='img' alt='nyam' height="300" />
    </div>
  </body>
  <script>
  var loadBinaryImage = function(url, cb) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        cb(this.response);
      }
    }
    xhr.open('GET', url);
    xhr.responseType = 'blob';
    xhr.send();
  }
  document.addEventListener('DOMContentLoaded', function () {
    loadBinaryImage('./image', function (blob) {
      var img = document.getElementById('img');
      img.src = URL.createObjectURL(blob);
    });
  });
  </script>
</html>

これを調べた動機

そもそも画像を表示するなら

<img src='http://localhost:3000/images/nyam.jpg' alt='nyam.jpg'>

で事足りるわけですが、 やんごとなき事情によりAuthorization: Bearer [token]がないと画像が取れねーよって状況になってるので調べました。 さてと動画というと… 206の応答を返してごにょごにょして…

こんな感じでできるっぽい。
重い動画の場合は知らん。
そもそもほかのドメインに動画読み取らせるのはなぁという…。

参考リンク

XMLHttpRequestで取得した画像バイナリをJavaScriptでロードする - kinjouj.github.io
AjaxでバイナリのJPEG画像データを受け取って表示する - Qiita