使用图像内容类型的HTTP响应显示图像

48
假设我有一个URL,但不知道它会返回什么。我使用javascript执行ajax调用该URL并获取内容。因此,我测试其内容类型并决定如何在我的网页中显示响应。
如果内容为json或html或任何其他文本,则根据需要附加格式化的内容。
现在,当内容类型为图像时,我会在响应中获取图像数据,该数据未经过base64编码。当然,我需要在常规的<img>标签中显示图像。这就是我卡住的地方。
是否有一种方法可以从其内容数据中显示图像?
编辑
只是为了明确起见,以下是我收到的响应内容:
"�PNG


IHDR��Nn�tEXtSoftwareAdobe ImageReadyq�e<fiTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:8E935AD20E206811822AA1DC23D37A5E" xmpMM:DocumentID="xmp.did:606C15E3DC2311E2A81EB553B5E13CE0" xmpMM:InstanceID="xmp.iid:606C15E2DC2311E2A81EB553B5E13CE0" xmp:CreatorTool="Adobe Photoshop CS5 Macintosh"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:0E49679B0D20681192B0DE3AF6794EF0" stRef:documentID="xmp.did:8E935AD20E206811822AA1DC23D37A5E"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�,��
3IDATx�읿R�JGI&m�����I����؅K((MC7�nH����%���ef����0���u�� i%����:�`K�{�ӷ������u�>���(����(����(����(����(����(����(����(����(����(��((��((��((��((��(���&؅�b1�ϟ׬V��t���j�T*��e��R��t�����c0�&��|}yy����ns�|Cc�l���7k�����ju:�Eٴ����")Ye�
W�U�Mu+"n�����3
����zzz*c��%����K�g4�&�T���z=_����G���@ū�(�Rġ�ng��^������@�F���2G_��],t�Fb:�����^������@٨  ��n�F#�`����|���<��_!��z���,��?�p}��U�����I}���
��h�6N��}||$hIY���p^IR?��
(k*��D�c���)�����s�*l�e�n-}��o��f:��Pְ[.��ʚKdP�be
�!9��,ʺh��!�r����|����>}��o����λW.��#�5�    
�5IY)Zx�'ʚ4�:88��P��̫����P֟Z��玍�czeM�51(()��4����0f�P�03���A�'���Y�5)he�xTʚ�����|��eQ�$�j�jF���~AY�~_������A��`����dOZ�=��f��%�{�}��Qi6�����+U,ʚ4N��E��(�J9^s�m�e� ǜ#bQ6�5�D,��G٘���e��?~��(?h3����*V
��
!��-V*���[ڜ�݉,���v�����2����    �Pְ8�PeQ��d0�g.eM�I�'�����}�
wˠlb�F��|������GٝY/..^^^dl���nU0����hv������������)m�������ec��z�yK�����ְn淳9������=�lT����4�q�'''�E)j��6q��b��:��T�U���F����%�܈M�� � �ْ���,��766�Ŭ���[ ��!;���7)x�9)�/�����S�*��������i��GAJ�~����jMh*�j�f�Y��UV�k8��G9r�v�^����O����\W 9}^V�q�`(�ʄb)+�9���IVj��k���������K�x�-֊��Z�Pe���h4�L�k�O8[*3ާ�;�`���b���qAFi�(U��\.�C�6_�ݮo(�Ri8���`P��k���P�դ&�|?Ǒ#���o=�V��dĵp�K���h�I  N�)%fY�I���Ǡ�LpWq��v"�ʦ��*��4^G4bsn��J7h�^*�z�����{���V�����(+}#����=�$�(+�z!H�><<���SJD�¯e� �Q6��xAxuu%rx�]v)�4�Y%�d�rK���z��x��Q�
:;�h�Iu�mZ�h��bC�������� F���g�וּ�B�AY��lje�Q]Ā\�V�y5ʆ��3�rߔ�x�_qN����� h�W6t�S�<??{{t��h8�l�ș:�  ��mE��Q�;Y*{��&�`0�x�������(V   f|��Yˆ���qfH�Z��z��i\�S3�LP6�/�� h��nП������>γ?NP6��2LaA/VP؜q!�2�Q6k�U��oWa�(��PK��+��V���(ky�0_�g��fIe����*;����t��A?W\)�qb��մ�lb���*�ex�˦y#�ir\�4��bWs�:9�
]�m�����K��=�瘲�����_�)��K���O�Ќ�R6�x�Ƽ"J���}Q�����)+�^�ymS�������kP��B6蔪�J}���/��٘�+�COo���f�01��5OY��{O�ێ����Ӫ1Q6��P�ޔ�䌬ɑc��:�����G�>gd���0e��{��Уț��L�73LY}�wsO��*��t��p�fe�*�\k�d�f*k5�o�Ԭa�jUx��F9�6G+e�e�R�n*���0��k��10��v6
�$`Vm�_w�v���pm�Y#0��ժ*�T6J-�j��*U��&���Γ���Z�X)kzU`�vyW">�9��|�)��]����F�;�e�E���*(�����ʂg����%�}���,�,��,�,�&���/���Q���0��0e#�0��T*�lZ-�~!�@R��V5l��j���>Em�)p}}mֹ���뫉m=�χá��ׁ���^�g\�e��.b��߿Y$�U% �v:�JX{�up^�8���]��@��_��Z��&��t<o{W��T*1�V���+��OOO��Wr��������L-��������~�kh�J�V��ڏR�]��b�r���1�Bu_�p����zq�W2X$�o�}"�HYYS.��o��S(RK�V+��}\a�7�;�)_���A�d��1#Y$vl�{��ͭ��!���i����T�e�X�
(��((��((��((��((��((��((��((��((��((��(����(����(����(����(��`/�0a�����IEND�B`�"

请查看此链接:https://dev59.com/EGIj5IYBdhLWcg3wpmoH#20048852 - user2421690
5个回答

39
var rawResponse = "�PNG...."; // truncated for example

// convert to Base64
var b64Response = btoa(rawResponse);

// create an image
var outputImg = document.createElement('img');
outputImg.src = 'data:image/png;base64,'+b64Response;

// append it to your page
document.body.appendChild(outputImg);

1
这绝对应该是规范答案。另外,我认为值得一提的是,在这种情况下btoa会起作用,但需要借助unescapeencodeURIComponent来处理UTF-8。 - David-SkyMesh
32
喜欢这种方法。但在我的情况下,btoa 抛出了这个错误:Uncaught InvalidCharacterError: 'btoa' failed: The string to be encoded contains characters outside of the Latin1 range. 即使我做了 unescape(encodeURIComponent(rawResponse))。 顺便说一下,unescape 似乎已经被弃用了。 - ArVan
1
我正在使用文件路径上传图像,但在接收时,我得到了类似于上面的原始数据,但我无法将其转换为base64。btoa提供了一些其他结果,有任何想法为什么btoa没有提供base64? - Mohan Gopi
5
这对于 JPEG 图片来说是不同的吗?我使用 JPEG 图片也遇到了同样的问题,但这种方法似乎不起作用。在将所有内容转换后,我得到了一个有趣的图标,它会在前端显示当没有图片存在时;<img src="data:image/jpg;base64,77+977+977+977+9ABBKRklGAAEBAQBIAEgAAO+/ve+/vRDvv71FeGlmAABNTQAqAAAACAAFARIAAwAAAAEAAQAAATEAAgAAAC4AAAhWATIAAgAAABQAAAjvv73vv71pAAQAAAABAAAI77+977+9HAAHAA....................vv73vv71uM++/vWnvv70R77+9dU/vv71c77+9BADvv70Zbe+/vQTvv71UdO+/ve+/vUXvv73vv71577+9B2t+HWjvv73vv73vv73vv73vv73vv70="> - zaf187
@waqask87,你找到了content-type为jpeg的解决方案吗? - Rahul

21

我尝试过接受的答案,但它对我没有起作用。这是我的解决方案:

  1. 我正在使用fetch下载图像,因此需要将响应读取为blob
let data;
fetch(url).then(response => {
  response.blob().then(blobResponse => {
    data = blobResponse;
  })
});
  1. 显示blob作为图像
const urlCreator = window.URL || window.webkitURL;
document.getElementById('myImage').src = urlCreator.createObjectURL(data);

1
实际上,这是一个有效的答案,并由Mozilla在此处此处进行了指导。 - buncis
这是对问题的最佳答案。 - Ahmed Sayed Sk

1

解决方案

使用blob

  • 解决方案1

    const response = await fetch(`...`)
    const responseBlob = await response.blob()
    const img = document.createElement('img')
    img.src = URL.createObjectURL(responseBlob)
    document.querySelector(`body`).append(img)
    
  • 解决方案2

    从blob中获取URI.scheme.data您可以参考https://dev59.com/RlcP5IYBdhLWcg3wP3sU#50463054

    下面的示例(情况2)将向您展示详细信息。

示例

这个示例是从GitHub的某个仓库获取图像。

/**
 * @param {int} solutionNumber: I provide two solutions both can achieve.
 * @param {string} owner
 * @param {string} repo
 * @param {string} path
 * @param {string} branch: branch name or you can use SHA1
 * @param {string} token: Used while your repository is private. https://github.com/settings/tokens
 */
async function ShowGithubImg(solutionNumber, owner, repo, path, branch = "master", token = "") {
  const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${branch}`, {
    // method: "GET",
    headers: {
      accept: 'application/vnd.github.v3.raw',
      // authorization: `token ${token}`
    }
  })
  if (!response.ok) {
    const errMsg = await response.text()
    throw Error(`${response.statusText} (${response.status}) | ${errMsg} `)
  }

  const responseBlob = await response.blob()

  const img = document.createElement('img')

  switch (solutionNumber) {
    case 1:
      img.src = URL.createObjectURL(responseBlob)
      break
    case 2:
      let uriData = ""
      blob2bas64 = async (blob) => {
        const promise = new Promise((resolve, reject) => {
          const reader = new FileReader()
          reader.onload = function () { // use promise to wait until onload finished
            console.log(this.result) // you can see its media type is: application/vnd.github.v3.raw // https://docs.github.com/en/rest/overview/media-types
            uriData = this.result // <--- `this.result` contains a base64 data URI
            resolve()
          }
          reader.readAsDataURL(blob)
        })
        await promise
      }

      await blob2bas64(responseBlob)
      img.src = `${uriData}`
      break

  }
  document.querySelector(`body`).append(img)
}

for (const solutionNumber of [1, 2]) {
  ShowGithubImg(solutionNumber, "CarsonSlovoka", "excel", "app/urls/static/app.ico", "807dd79")
}

URI

@Lostsource的回答提到了统一资源标识符。由于这个问题只涉及图片,但有些人可能有其他格式(image/jpeg),实际上,URI.scheme.data的格式是:

data:<mediatype>[;base64],<data>

你可以在统一资源标识符上看到它。

你只需要知道mediatype常见媒体类型列表)。

例如:image/jpeg

data:image/jpeg;base64,<data>


0
我会使用canvas toDataURL将图像转换为base64,然后将其附加到DOM中:
var rawResponse = 'PNG'; // This is your response object
var encodedResponse = btoa(rawResponse);

var img = new Image();
var container = document.getElementById('newImg');

img.src = 'data:image/gif;base64,' + encodedResponse;

img.onload = function() {
container.appendChild( img );
};

有关btoa的更多信息


1
我在前端没有图像URL,只有内容。我不确定如何使用该数据创建画布。 - ArVan

0

我们可以获取响应并将其绑定到我的HTML表单。

1).ts文件页面:-

imageData : any ;

response => {
    var b64Response = btoa(response);
    this.imageData = 'data:image/png;base64,' + b64Response;
  }

2) .html 文件页面:

      <img [src]="imageData" class="img-thumbnail">

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