web-dev-qa-db-ja.com

ローカルコピーを作成せずに、URLのみを持つSharpを使用し、async / awaitを使用して、NodeJSで画像のサイズを変更するにはどうすればよいですか?

利用可能な画像処理ライブラリがNodeJSの Sharp である環境で画像をスケーリングしています。パイプベースなので安定していますが、TypeScriptに変換し、可能であればAsync/Awaitを使用して設定する必要があります。ほとんどの部分は準備できていますが、私が直面している問題は、私が持っているのは画像のURLだけであり、Sharpは文字列URI(ローカルファイルのみ)またはバッファのいずれかを期待しているという事実です。

現在、私はパッケージの Axios を使用して、応答のdataプロパティで取得できる文字列として画像をフェッチしています。私はBuffer.from(response.data)によって文字列から作成されたバッファーをSharpに供給していますが、メタデータを収集して画像を「操作」するまで問題はありません。この時点で、エラーがスローされます:[Error: Input buffer contains unsupported image format]。しかし、古いシステムで機能していたので、イメージが有効であることを知っており、依存関係を変更していません。

QuokkaJSを使用してテストを行ったところ、次のPoCが失敗し、正常に機能する必要があります。

import axios from 'axios';
import Sharp from 'sharp';
const url = 'https://dqktdb1dhykn6.cloudfront.net/357882-TLRKytH3h.jpg';

const imageResponse = await axios({url: url, responseType: 'stream'});
const buffer = Buffer.from(imageResponse.data);
let src = new Sharp(buffer);
const src2 = src.clone();//this is simply because it will end up being a loop, if this is the issue let me know.
try {
    await src2.jpeg();
    await src2.resize(null, 1920);
    await src2.resize(1080, null);
    const metadata = await src2.clone().metadata();//this is where it fails
    console.log(metadata);
} catch(e) {
    console.log(e);//logs the mentioned error
}

誰かが私が間違って何をしているのか考えている場合、または追加してほしい特定の情報がある場合は、お知らせください!画像データをパイプ処理するneedの場合は、お知らせください。文字列でpipe is not a functionを取得して直接パイプしようとしました(これは理にかなっています)。

アップデート#1:

問題を解決してくれたコメントについて@Thee_Sritabtimに感謝します。基本的に、私はストリームベースの文字列をバッファに変換しようとしていました。代わりに、リクエストがArrayBufferに対するものであることを宣言し、binaryのタイプを宣言しながら、それをSharpにフィードする必要がありました。 PoCの実際の例は次のとおりです。

import axios from 'axios';
import Sharp from 'sharp';
const url = 'https://dqktdb1dhykn6.cloudfront.net/357882-TLRKytH3h.jpg';

const imageResponse = await axios({url: url, responseType: 'arraybuffer'});
const buffer = Buffer.from(imageResponse.data, 'binary');
let src = new Sharp(buffer);
try {
    await src.jpeg();
    await src.resize(null, 1920);
    await src.resize(1080, null);
    const metadata = await src.metadata();//this was where it failed, but now it prints an object of metadata
    console.log(metadata);
} catch(e) {
    console.log(e);//Doesn't catch anything any more!
}
4
AntonMiles

axios応答からバッファを取得するには、responseTypeを_'arraybuffer'_に設定する必要があります。

_const imageResponse = await axios({url: url, responseType: 'arraybuffer'})
const buffer = Buffer.from(imageResponse.data, 'binary')
_

または、

sharp()の入力としてストリームを使用することもできるため、responseTypeを_'stream'_に保つことができます

_const imageResponse = await axios({url: url, responseType: 'stream'})

const src = imageResponse.data.pipe(sharp())
//...
const metadata = await src.metadata()

_
1
thammada.ts