如何使用仅 URL、async/await 且不创建本地副本的 Sharp 在 NodeJS 中调整图像大小?
How can you resize an image in NodeJS using Sharp having only a URL, using async/await, and without a local copy being created?
我工作的环境中可用的图像处理库是 NodeJS 的 Sharp 用于缩放图像。它一直很稳定,因为它是基于管道的,但我的任务是将它转换成 TypeScript,并在可能的情况下使用 Async/Await 进行设置。我已经准备好大部分内容,但我面临的问题是我所拥有的只是图像的 URL,而 Sharp 需要字符串 URI(仅限本地文件)或缓冲区。
目前,我正在使用包 Axios 来获取图像作为响应中 data
属性 可检索的字符串。我一直在将 Buffer.from(response.data)
从字符串创建的缓冲区输入到 Sharp 中,直到我尝试 "work" 通过尝试收集元数据来处理图像之前,它没有任何问题。此时它抛出一个错误:[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
}
如果有人知道我做错了什么,或者有任何具体信息希望我添加,请告诉我!如果我需要来传输图像数据,请告诉我。我试图直接通过管道在字符串上获得 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!
}
要从 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()
我工作的环境中可用的图像处理库是 NodeJS 的 Sharp 用于缩放图像。它一直很稳定,因为它是基于管道的,但我的任务是将它转换成 TypeScript,并在可能的情况下使用 Async/Await 进行设置。我已经准备好大部分内容,但我面临的问题是我所拥有的只是图像的 URL,而 Sharp 需要字符串 URI(仅限本地文件)或缓冲区。
目前,我正在使用包 Axios 来获取图像作为响应中 data
属性 可检索的字符串。我一直在将 Buffer.from(response.data)
从字符串创建的缓冲区输入到 Sharp 中,直到我尝试 "work" 通过尝试收集元数据来处理图像之前,它没有任何问题。此时它抛出一个错误:[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
}
如果有人知道我做错了什么,或者有任何具体信息希望我添加,请告诉我!如果我需要来传输图像数据,请告诉我。我试图直接通过管道在字符串上获得 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!
}
要从 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()