Node.jsで画像をダウンロード保存し、リサイズ・サムネイル作成してみよう
この記事は約4 分で読めます。
目次

今回は画像をダウンロードしてリサイズしたり、サムネイルを作成する工程を同期・非同期を考慮しながら考えてみます。
Node.jsでプログラムを組む場合、同期・非同期を意識しないと意図しない結果が返ってきます。
よくあるのが処理が完了しないうちに最終処理、特に出力や保存が実行され、空や壊れたデータが出力されるケースです。
それらを踏まえ、今回の課題のエッセンスは3つ。
- Npde.jsで画像をダウンロードする
- ダウンロードした画像の保存完了を待ってからサムネイルを作成する
- Node.jsでサムネイルを作成する
それでは具体的なコードを確認しながら見ていきましょう。
画像をダウンロード
今回はウェブサイトから画像をダウンロードすることを想定しています。
また開発にはExpressを利用しています。
1const request = require('then-request');
2const easimages = require('easyimage');
3
4request('GET', 'イメージ画像URL').done(function(body) {
5 fs.writeFile('/画像保存パス/画像ファイル名', body.getBody(), 'binary');
6 easimages.thumbnail({
7 src: '/画像保存パス/画像ファイル名',
8 dst: '/画像保存パス/サムネイルファイル名',
9 width: 80,
10 height: 80
11 });
12});
1行目:最初、画像ダウンロードにsync-request
モジュールを使っていましたが、このモジュールは使わないで!とnpm公式ページに書いてあったので、then-request
に修正しました。
画像を保存する
今回は最終的にダウンロードした画像からサムネイルを作成することが目的です。
ダウンロードした画像の保存が完了する前にサムネイルの作成を行おうとすると元画像ファイルがないということでエラーになります。
そこで、画像をダンロードできたらdone
で次の処理(保存)へ渡しています。
4行目:request('GET', 'イメージ画像URL').done(function (rebodys) {
5行目:fs.writeFile('/画像保存パス/画像ファイル名', body.getBody(), 'binary');
で画像ファイルを保存します。
body.getBody()
で画像のバイナリデータを取得できますので、ファイルに書き込みます。
サムネイルの作成(Node.jsによる画像編集)
サムネイルを作成してみましょう。
2行目、easyimage
モジュールを使い、画像編集します。
1$ npm install easyimage --save
easimages.thumbnail({})
のパラメータ
- src:編集前画像パス+ファイル名
- dst:編集後画像パス+ファイル名
- width:サムネイル横幅
- height:サムネイル縦幅
例では正方形のサムネイルの作成を想定して、幅と高さを同じにしていますが、縦長・横長のサムネイルも作成できます。
またeasyimage
ではresize
(リサイズ)などもできますので、色々画像編集に使えます。
画像の処理方法によってオプションの指定が異なりますので最初は少し戸惑うかもしれません。
一例として画像をトリミングしてリサイズするrescrop
の記述例を書いておきます。
1easyimg.rescrop({
2 src: '/画像保存パス/画像ファイル名',
3 dst: '/画像保存パス/変換後ファイル名',
4 width:160, // リサイズ幅
5 y: 50, // トリミング開始位置(Y座標)
6 cropWidth: 160, // トリミング後の画像の幅
7 cropHeight: 85 // トリミング後の画像の高さ
8});
この例ですと、まず幅160pxにリサイズし(高さは自動計算)、座標(0, 50)の位置から160 x 85の大きさにトリミングしています。
オプションの詳細は下記参照。
Node.jsによる画像のwebp変換の記事はこちらにありますので、サムネイル化した画像をさらにwebp化する場合には参考にしてください。
まとめ
画像の取扱いというテーマに、
- ファイルのダウンロード
- ファイルの保存
- doneによる順番実行
- 画像編集
の4つのナレッジが含まれていました。
どれか一つのコードでも参考になれば幸いです。
タイミングによって画像が保存されず、サムネイルを作成するにも元画像がない!という事態に遭遇したので、上記のようなコードにまとめてみましたが、もっと他にスマートな記述があるような気がしますので、試行錯誤したいと思います。