关于使用 JavaScript 显示外部 url 图像的不同方式的困惑

Joj*_*oji 14 html javascript base64 fetch-api

我最近了解到似乎有多种方法可以在网页上显示图像。

第一种方法是直接将 URL 分配给图像元素的 URL

const img = new Image();

img.onload = () => {
  document.querySelector("#myImage").src = url;
};
img.onerror = () => {};

img.src = imageUrl;
Run Code Online (Sandbox Code Playgroud)

我最近学到的另一种方法是使用fetch

fetch(imageUrl)
    .then((response)=>response.blob())
    .then((blob)=>{
       const objectUrl = URL.createObjectURL(blob)
       document.querySelector("#myImage").src = objectUrl;
})
Run Code Online (Sandbox Code Playgroud)

我对这两种方法都有一些疑问:

  1. 我很熟悉,fetch但我通常用它来获取 JSON。在我看来,第二种获取fetch图像的方法就像我们通过 HTTP 获取该图像文件的原始二进制数据,而第一种方法是我们委托浏览器启动Get获取该图像的请求。但从服务器的角度来看,在如何发送图像方面没有区别?我这样理解对吗?

  2. 在什么情况下我们应该优先选择一种方法而不是另一种?我觉得第二种方法比第一种方法会出现很多 CORS 问题,但不确定具体原因。

  3. 还有其他方法可以在网页上显示图像吗?当人们谈论图像时,我经常听说 Base64 编码/解码。response.blob()base64与ie第二种方法有关吗?还是有所不同?如果是这样,有人可以给我一个使用 base64 显示图像的例子吗?

  4. 最后,我认为显示图像一直是我前端或 Web 开发知识中的一个漏洞。请随时推荐有关此主题的任何好的资源。

Abr*_*ham 6

回答您的问题

  1. 从服务器端来看,除了浏览器可以发送的标头和信息之外,它基本上是相同的,而在 fetch 中,您可以完全控制标头
  2. fetch 方法可用于需要您可能在服务器中实现的请求或安全传输的更灵活或更进一步的参数。例如,需要一个包含某些数据的标头或正文的发布请求,以允许图像传输……或者进行灵活的传输,例如可以将数据放入块中,以便稍后在呈现之前组装和操作。
  3. 使用 base64 几乎与二进制相同,尽管它用于通过设计用于传输文本的介质来传输图像/数据。这是因为 base64 使用 ascii 数字和字母来表示任何数据。

在这里,您可以看到由 Base64 字符串字符生成的图像,没有任何链接

<img style="width:64px; height:64px;" src="data:image/png;base64,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"></img>
Run Code Online (Sandbox Code Playgroud)

这也有助于将图像作为文本直接嵌入代码中,将其作为 url 参数传递,甚至可以将图像放入JSON文件中。在某些情况下,它的性能也比使用 gzip 等压缩的二进制图像更好。


DDo*_*men 5

直接回答

\n
    \n
  1. 是的,服务器可以发送任何类型的数据(任何数据都只是数字的二进制连续,甚至文本和字符)。客户通常会遵循某些标准来尝试理解内容。
  2. \n
  3. 如果您不需要操作图像,我建议您避免任何请求,因为浏览器可以为您处理它。请注意,onlyfetch几乎不会受到 CORS 的影响,因为它不发送跨域 cookie(请参阅MDN - 使用 fetch)。如果您需要更多控制,可以使用XMLHTTPRequest。blob 的使用继承自旧的 Web 方法,那些时代还ArrayBuffer没有发明,并且它是 Web 环境中二进制数据的唯一包装器。由于多种原因,它仍然受到支持。
  4. \n
  5. 实际上比你想象的要少(只有 1)!检查解释...
  6. \n
  7. 图像资源很大程度上取决于您需要什么样的处理...只是显示图像?MDN和CSS-tricks都有很多技巧,你只需要搜索它们即可。如果您想处理图像,则需要进一步查看画布元素,并且通常的资源很少或几乎与游戏制作(出于明显的原因)、MDN 以及 CSS 资源技巧中的内容有关。
  8. \n
\n

解释

\n

什么是图像?

\n

我认为您对浏览器显示图像的概念有偏见。

\n

那么图像到底是什么?二进制数据。

\n

实际上,浏览器(或一般计算机)显示图像的方法只有一种,那就是使用字节数组,它是图像像素的扁平视图。因此,最终您总是需要向浏览器提供可解释为原始图像(通常是一组rgb(a)像素)的二进制数据。

\n

是的,在计算机上显示图像只有“一种”方式。但我们可以通过不同的方式来表示该图像。

\n

编码

\n

在底层,不同的计算机以不同的方式表示数字,因此网络标准决定以所谓的RGB8或RGBA8编码(红-绿-蓝(-Alpha)-NumBits,8 位 = 1 字节)来表示图像。这意味着每个像素都由 4 个字节(数字)的数组表示,每个字节的范围从 0 到 255。该数组是浏览器唯一将其视为图像的东西。

\n

最后你的图像是这样的:

\n
// using color(x, y) to describe the image pixels\n[ red(0, 0), green(0, 0), blue(0, 0), alpha(0, 0), red(1, 0), ... ] =\n[ 124, 12, 123, 255, 122, ... ]\n
Run Code Online (Sandbox Code Playgroud)\n

现在您可以将图像视为像素的线性阵列,我们可以决定如何将其写在一张纸上(我们的“代码”)。浏览器(通常和历史上)将 HTML 文件中在 Web 上发送的每个数据包解析为纯文本,因此我们必须使用字符来描述我们的图像,标准是仅使用UTF - 8(字符编码,ASCII 的超集)。例如,我们可以在 JS 中将其写为数字数组。

\n

但是看一下数字 255。每次您在 newtork 上发送该号码时,您都会发送 3 个字符:\'2\'、\'5\'、\'5\'。网络仅与字符进行通信,所以......有没有一种方法可以使该数字紧凑表示,以便发送尽可能少的字节(拯救那些连接速度慢的人!)?

\n

Base64是最著名的编码,用于以最紧凑的方式描述线性数组,因为它将 255 个字符压缩为 1 或 2 个字符(取决于序列)。我们可以去掉一些通常用作字母的字符来表示更多的数字,而不是表示以 10 为基数的数字。所以\'11\' become \'a\', \'12\' => \'b\', \'13\' => \'c\', ..., \'32\' => \'a\', ..., \'63\' => \'Z\', \'64\' => \'10\', \'65\' => \'11\', ..., \'128\' => \'20\',等等。此外,该算法利用更低级的表示来在一个字符中编码更多的数字(这就是为什么你有时会在末尾看到一些“=”)。

\n

看看同一图像的不同表示:

\n
// JavaScript Array\n[ /* pixel 1 */ 124, 12, 123, 255, /* pixel 2 */ 122, 12, 56, 255 ] // 67 characters\n// (30 without spaces and comments)\n\n// Base64\nfAx7w796DDjDvw== // 16 characters\n// Base32\n3sc3r7v3qc1o7vAb== // 18 characters (always >= Base64)\n
Run Code Online (Sandbox Code Playgroud)\n

很容易理解为什么他们选择 base64 作为通用算法(这个例子只计算 2 个像素)。

\n

(Base32 图像示例)

\n

格式

\n

现在想象一下在网络上发送一张 4K 图像,其尺寸为 3\'656 \xc3\x97 2\'664。这意味着您要在互联网上发送 9\'739\'584 个像素,每个像素 4 个字节,总共 38\'958\'336 个字节 (~39MB)。再想象一下,如果图像是全黑的(我们可以用一个像素来描述整个图像),那是多么浪费……这太多了(特别是对于低连接),为此他们发明了一些算法来描述更紧凑的图像,我们称之为图像格式。PNG 和 JPEG/JPG 是压缩图像的格式示例(jpg 4k 图像 ~8MB,png 4k 图像可以从 ~2MB 到 ~22MB 变化,具体取决于某些参数和图像本身)。

\n

有人将压缩技术提高到了一个新的水平,建立了gzip压缩标准格式(对已经压缩的图像或任何其他类型的文件的通用压缩算法)。

\n

在浏览器上绘图

\n

在本次旅程结束时,浏览器允许您以两种不同的方式绘制内容:URI和ArrayBuffer。

\n
    \n
  • URI:您可以将它与<img>css 一起使用,通过设置src元素的属性或设置任何可以获取图像URL作为输入的样式属性。
  • \n
  • ArrayBuffer:通过操作<canvas>.context缓冲区(这就是我们上面讨论的线性数组)
  • \n
\n

显然,浏览器还允许在两种方式之间进行转换或切换。

\n

统一资源标识符

\n

URI是我们定义特定内容的方式,它可以是存储的资源(URL- 除 之外的所有协议data,例如http(s)://,ws(s)://或file://)或由字符串(协议)描述的正确缓冲区data。

\n

当您请求图像时,通过设置src属性,您的浏览器会解析 URL,如果它是远程内容,则会发出检索它的请求并以正确的方式(格式和编码)解析内容。同样,当您拨打电话时,fetch您是在要求浏览器请求远程内容;该fetch函数可以通过不同的方式获得响应:

\n
    \n
  • 文本,只是一堆字符(通常用于解析 JSON/DOM/XML)
  • \n
  • 二进制数据,分为:\n
      \n
    • ArrayBuffer,它是我们上面讨论的图像线性阵列的表示
    • \n
    • Blob,它是通用类文件对象的抽象表示(它也封装了一个内部ArrayBuffer)。它Blob类似于指向浏览器缓存中类似文件实体的指针,因此您不需要多次下载/请求同一文件。
    • \n
    \n
  • \n
\n
// using color(x, y) to describe the image pixels\n[ red(0, 0), green(0, 0), blue(0, 0), alpha(0, 0), red(1, 0), ... ] =\n[ 124, 12, 123, 255, 122, ... ]\n
Run Code Online (Sandbox Code Playgroud)\n

因此,现在您必须告诉浏览器如何理解从响应中返回的内容。您需要将数据转换为可解析的 url:

\n
var encodedURI = `data:${format};${encoding},` + encodeBuffer(new Uint8Array(arrayBuffer));\nimage.src = encodedURI\n\n// for base64 encoding\nvar encodeBuffer = function(buffer) { return window.btoa(String.fromCharCode.apply(null, buffer)); } \n\n// for blobs\nimage.src = (window.URL || window.webkitURL).createObjectURL(blob);\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,浏览器不仅支持 base64,还支持其他编码,base32 也可用,但正如我们在上面看到的,使用起来不太方便。此外,也没有像btoa以 Base32 编码缓冲区这样的内置函数。

\n

另请注意,格式值可以是任何类型的MIME 类型,例如image/png|jpg|gif|svg或text/plain|html|xml、application/octet等。显然,只有图像类型才会显示为图像。

\n

file://当没有从远程服务器(使用或协议)请求资源时,data图像通常会同步加载,因此一旦您设置了 URL,浏览器就会读取、解码并将缓冲区显示在您的图像中。这有两个后果:

\n
    \n
  1. 数据在本地管理(无需互联网连接)
  2. \n
  3. 数据是同步处理的,因此如果图像很大,您的计算机将陷入处理直到最后(了解为什么data在最后的特殊部分中对视频或大数据使用协议是一种不好的做法)
  4. \n
\n

URL 与 URI

\n

URI是资源的通用标识符,是检索资源的位置URL的标识符。通常在浏览器上下文中几乎是一个重叠的概念,我发现这张图片比千字解释得更好:\nURL 与 URI

\n

实际上是data一个URI,每个带有协议的请求实际上是一个URL

\n

边注

\n

在您的问题中,您通过“设置图像元素 url”将其写为替代方法:

\n
fetch(imageUrl)\n    .then((response)=>response.blob())\n    .then((blob)=>{\n       const objectUrl = URL.createObjectURL(blob)\n       document.querySelector("#myImage").src = objectUrl; // <-- setting url!\n})\n
Run Code Online (Sandbox Code Playgroud)\n

但请注意:您实际上设置了图像元素源 URL!

\n

帆布

\n

该<canvas>元素使您可以完全控制图像缓冲区,并进一步处理它。您可以在其中绘制数组:

\n
var canvas = document.getElementById(\'mycanvas\');\n// or offline canvas:\nvar canvas = document.createElement(\'canvas\');\ncanvas.width = myWidth;\ncanvas.height = myHeight;\n\nvar context = canvas.getContext(\'2d\');\n\n// exemple from array buffer\nvar arrayBuffer = /* from fetch or Blob.arrayBuffer() or also with new ArrayBuffer(size) */\nvar buffer = new Uint8ClampedArray(arrayBuffer);\nvar imageData = new ImageData(buffer, width, height);\ncontext.putImageData(iData, 0, 0);\n\n// example image from array (2 pixels)\nvar data = [\n//   R    G    B    A\n    255, 255, 255, 255, // white pixel\n    255,   0,   0, 255  // red pixel\n];\nvar buffer = new Uint8ClampedArray(data);\nvar imageData = new ImageData(buffer, 2, 1);\ncontext.putImageData(iData, 0, 0);\n
Run Code Online (Sandbox Code Playgroud)\n

(注意ImageData需要一个RGBA数组)

\n

要恢复ArrayBuffer(您也可以在之后重新插入image.src),您可以执行以下操作:

\n
var imageData = context.getImageData(0, 0, canvas.width, canvas.heigth);\nvar buffer = imageData.data; // Uint8ClampedArray\nvar arrayBuffer = buffer.buffer; // ArrayBuffer\n
Run Code Online (Sandbox Code Playgroud)\n

这是如何处理图像的示例:

\n
// reading image\nvar image = document.getElementById(\'myimage\');\nimage.onload = function() {\n    // load image in canvas\n    context.drawImage(image, 0, 0);\n   \n    // process your image\n    context.fillRect(20, 20, 150, 100);\n    var imageData = context.getImageData(0, 0, canvas.width, canvas.height);\n    imageData.data[0] = 255;\n\n    // converting back to base64 url\n    var resultUrl = window.btoa(String.fromCharCode.apply(null, imageData.data.buffer));\n   \n    // setting image url and disabling onload\n    image.onload = null;\n    image.src = resultUrl;\n};\n\n// note src setted after onload\nimage.src = \'ANY-URL\';\n
Run Code Online (Sandbox Code Playgroud)\n

对于这一部分,我建议您查看Canvas 教程 - MDN

\n

特别的

\n

音频和视频的处理方式相同,但您必须以某种方式对时间和声音维度进行编码和格式化。您可以从 base64字符串加载音频/视频(对于视频来说不是个好主意)或在画布上显示视频

\n