使用Fetch API请求Blob图像并转换为Base64

26

我有一些图像将在React应用程序中显示。我向服务器执行GET请求,该请求返回BLOB格式的图像。然后我将这些图像转换为base64。最后,我将这些base64字符串设置为图像标记的src属性。

最近我开始使用Fetch API。我想知道是否有一种方法可以'一次性'进行转换。以下是一个示例来解释我的想法以及/或者使用Fetch API是否可能实现。我还没有在网上找到任何相关信息。

  let reader = new window.FileReader();
  fetch('http://localhost:3000/whatever')
  .then(response => response.blob())
  .then(myBlob => reader.readAsDataURL(myBlob))
  .then(myBase64 => {
    imagesString = myBase64
  }).catch(error => {
    //Lalala
  })

为什么不使用 Blob URL 或者原始 URL 呢? - Musa
我没有在src中使用URL,因为我获取的图像来自需要在标头中进行身份验证令牌的API。 - Desistreus
https://dev59.com/d2025IYBdhLWcg3wNTAV - cilf
4个回答

34

FileReader.readAsDataURL 的返回值不是 Promise。你必须按照旧的方式执行。

fetch('http://localhost:3000/whatever')
.then( response => response.blob() )
.then( blob =>{
    var reader = new FileReader() ;
    reader.onload = function(){ console.log(this.result) } ; // <--- `this.result` contains a base64 data URI
    reader.readAsDataURL(blob) ;
}) ;

通用函数:

function urlContentToDataUri(url){
    return  fetch(url)
            .then( response => response.blob() )
            .then( blob => new Promise( callback =>{
                let reader = new FileReader() ;
                reader.onload = function(){ callback(this.result) } ;
                reader.readAsDataURL(blob) ;
            }) ) ;
}

//Usage example:
urlContentToDataUri('http://example.com').then( dataUri => console.log(dataUri) ) ;

//Usage example using await:
let dataUri = await urlContentToDataUri('http://example.com') ;
console.log(dataUri) ;

你如何从一个函数中返回它? - lmat - Reinstate Monica
@Reinstate,你不能直接返回它。你必须返回一个Promise。请参见更新的答案。 - GetFree
我明白了。我只熟悉Promise.resolve,还不熟悉new Promise(resolve=> ... resolve(value); ...);,尽管现在看起来很明显。谢谢! - lmat - Reinstate Monica

10

感谢@GetFree,这是使用async/await编写的版本,并具有Promise错误处理:

const imageUrlToBase64 = async url => {
  const response = await fetch(url);
  const blob = await response.blob();
  return new Promise((onSuccess, onError) => {
    try {
      const reader = new FileReader() ;
      reader.onload = function(){ onSuccess(this.result) } ;
      reader.readAsDataURL(blob) ;
    } catch(e) {
      onError(e);
    }
  });
};

使用方法:

const base64 = await imageUrlToBase64('https://via.placeholder.com/150');

2

如果有人需要在Node.js中完成此操作:

const fetch = require('cross-fetch');
const response  = await fetch(url);
const base64_body = (await response.buffer()).toString('base64');

可以使用node-fetch代替cross-fetch。 - Dave Cole

0
这是将 blob 转换为图像 URI 的逻辑,源自 @Augustin Riedinger 的回答:
async function imageUrlToBase64(blob: Blob) {
  return new Promise((onSuccess, onError) => {
    try {
      const reader = new FileReader();
      reader.onload = function () {
        onSuccess(this.result);
      };
      reader.readAsDataURL(blob);
    } catch (e) {
      onError(e);
    }
  });
}

使用方法:

const res = await fetch(...);
const blob = await res.blob();
const uri = await imageBlobToBase64(blob);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接