将 Blob URL 转换为普通 URL

144
我的页面生成了一个类似这样的URL:"blob:http%3A//localhost%3A8383/568233a1-8b13-48b3-84d5-cca045ae384f"。我该如何将它转换为普通地址?我将其用作<img>标签的src属性。

2
即使解码了URL,它仍然是一个localhost链接。请查找其公共链接。(您正在使用哪个CDN?) - Raptor
我希望使用JavaScript。 - Jacob
使用stackvoverflow链接W3C,你真正的问题将是如何使它独立于你部署代码的环境。 - user1428716
有没有一种方法可以从 Blob 地址中找到公共 URL?这是我唯一拥有的值。 - Jacob
仅举例说明为什么我们不能直接打开或使用XHR访问视频src blob:xxxx.com/xxxx。这个blob是通过URL.createObjectURL(mediaSource)创建的。这里是示例 - Yilin Huang
显示剩余2条评论
7个回答

226

从JavaScript Blob 创建的 URL 无法转换为“普通” URL。

blob: URL 不是指在服务器上存在的数据,而是指您的浏览器当前在内存中为当前页面保留的数据。它将不可用于其他页面、其他浏览器或其他计算机。

因此,一般情况下,将 Blob URL 转换为“普通” URL 没有意义。如果您想要一个普通 URL,则需要将数据从浏览器发送到服务器,并让服务器像普通文件一样提供该数据。

至少在 Chrome 中,可以将 blob: URL 转换为 data: URL。您可以使用 AJAX 请求从 blob: URL “获取”数据(尽管实际上只是从浏览器的内存中取出数据,而不是进行 HTTP 请求)。

以下是示例:

var blob = new Blob(["Hello, world!"], { type: 'text/plain' });
var blobUrl = URL.createObjectURL(blob);

var xhr = new XMLHttpRequest;
xhr.responseType = 'blob';

xhr.onload = function() {
   var recoveredBlob = xhr.response;

   var reader = new FileReader;

   reader.onload = function() {
     var blobAsDataUrl = reader.result;
     window.location = blobAsDataUrl;
   };

   reader.readAsDataURL(recoveredBlob);
};

xhr.open('GET', blobUrl);
xhr.send();

data: URL可能不是您所谓的“普通”URL,而且可能会非常大。但是它们确实像普通URL一样工作,因为它们可以被共享;它们不特定于当前浏览器或会话。


26
如果 Blob URL 不指向服务器数据,那么为什么 YouTube 视频的 src URL 看起来像这样:src="blob:https%3A//www.youtube.com/44f26667-03f1-4978-9eed-af0cbf11dd67"(在 Chrome 中) - bhh1988
10
@bhh1988 这是一个非常有趣的发现。我不确定那里发生了什么。如果我尝试像这篇文章所描述的那样使用XMLHttpRequest检索它们的src blob URL,没有任何内容被返回。我的猜测是,要么(a)他们生成一个空的Blob URL用作占位符,同时从另一个来源中输入数据,要么(b)Blob以某种方式充当加密数据的代理(通过HTML5 Encrypted Media Extensions)。但是,我不确定这两者实际上该如何完成。 - Jeremy
28
看起来《媒体源扩展规范》允许JavaScript管理的媒体流创建Blob URL。这些不像本文讨论的静态数据的Blob URL,因此行为上有所不同,但它们仍然指向本地信息,而不是直接指向服务器上的数据。 - Jeremy
2
嗯,听起来没错。这很令人困惑,因为URL看起来真实而有意义,但如果它只是一个占位符,src的值就不重要了。 - bhh1988
4
我遇到了一个“Not allowed to navigate top frame to data URL: data:text/plain;base64,...”的错误。我可以获取数据,但是不允许使用“window.location”函数。 - loretoparisi
显示剩余4条评论

20

从 Blob URL 创建 Data URL 的另一种方法可能是使用 Canvas。

var canvas = document.createElement("canvas")
var context = canvas.getContext("2d")
context.drawImage(img, 0, 0) // i assume that img.src is your blob url
var dataurl = canvas.toDataURL("your prefer type", your prefer quality)

根据我在MDN上看到的,canvas.toDataURL在浏览器中得到了很好的支持。(除了IE<9,总是IE<9)


演示:

let blobToImage=(binaryUrl) => {
  var canvas=document.createElement("canvas")
  var img=document.createElement('img');
  img.src=binaryUrl;
  var context=canvas.getContext("2d")
  context.drawImage(img, 0, 0);
  return canvas.toDataURL();
}

let blobUrl = "https://cdn.pixabay.com/photo/2014/02/27/16/10/flowers-276014__340.jpg";
let imgUrl = blobToImage(blobUrl);
console.log(blobUrl);
console.log(imgUrl);


18
请注意,这当然只适用于图像数据,一些元数据可能会丢失! - minmaxavg
2
这样做会创建一个链接,但如果你跟随它,你只会得到一个黑色的框。 - Antfish
@Antfish,这不应该发生,对吧? - Pacerier

16

如果您想下载blob url视频/音频,这个回答对我有用。简而言之,您需要通过Chrome网络选项卡在所需网页上找到一个*.m3u8文件,然后将其粘贴到VLC播放器中。

另一篇指南向您展示了如何使用VLC Player 保存流媒体文件


更新:

从blob url下载视频的另一种方法是使用批量下载器并将文件合并在一起。

下载视频部分

  1. 在Chrome开发工具中打开网络选项卡

输入图片描述

  1. 重新加载网页
  2. 过滤.m3u8文件

输入图片描述

  1. 查看所有筛选出的文件并找到包含“ .ts”文件的播放列表。它应该类似于:

在此输入图片描述

  1. 你需要想办法提取那些链接。可以手动下载并编辑文件,也可以使用其他方法。如你所见,这些链接非常相似,唯一不同的是视频的序列号:'s-0-v1-a1.ts', 's-1-v1-a1.ts'等等。

    https://some-website.net/del/8cf.m3u8/s-0-v1-a1.ts

    https://some-website.net/del/8cf.m3u8/s-1-v1-a1.ts

    https://some-website.net/del/8cf.m3u8/s-2-v1-a1.ts

以此类推,直到.m3u8播放列表文件中的最后一个链接。这些.ts文件实际上是你的视频。你需要下载它们。

  1. 对于批量下载,我更喜欢使用Chrome的Simple Mass Downloader扩展程序(https://chrome.google.com/webstore/detail/simple-mass-downloader/abdkkegmcbiomijcbdaodaflgehfffed)。

  2. 如果您选择使用Simple Mass Downloader,您需要:

    a. 选择一个模式链接。

输入图像描述

b. 在地址栏中输入您的链接,但只有一个修改:每个下一个视频变化的部分需要用方括号[0:400] 中的模式替换,其中0是第一个文件名,400是最后一个。所以您的链接应该长这样:https://some-website.net/del/8cf.m3u8/s-[0:400]-v1-a1.ts

之后点击导入按钮将这些链接添加到Mass Downloader的下载列表中。

输入图像描述

c. 接下来的操作可能会要求您为每个下载的视频指定目标文件夹。因此强烈建议在Chrome设置中指定默认下载文件夹并禁用Chrome设置中的选择目标选项。这将节省您很多时间!另外,您可能想要指定这些文件将存储在哪个文件夹中:

输入图像描述

c1. 单击“全选”复选框以选择下载列表中的所有文件。

输入图像描述

c2. 单击SMD扩展窗口右下角的“下载”按钮。它会带您进入下一个选项卡以开始下载。

输入图像描述

c3. 点击“开始选择”,这将自动将所有视频下载到下载文件夹。

输入图像描述

就是这样!只需等待所有文件下载完成,然后您就可以通过VLC播放器或支持.ts格式的任何其他播放器观看它们。但是,如果您想要一个视频而不是您已经下载的视频,请将这些迷你视频拼接在一起。

合并视频部分

由于我正在使用Mac,所以不知道Windows上该如何操作。如果您是Windows用户,并且想要合并这些视频,请随时在Google上搜索Windows解决方案。下面的步骤仅适用于Mac。

  1. 在要保存新视频的文件夹中打开终端
  2. 输入cat并按下空格键
  3. 打开下载了.ts视频的文件夹。选择您想要合并的所有.ts视频(使用鼠标或cmd+A
  4. 将它们拖放到终端中
  5. 按下空格键
  6. 按下>
  7. 按下空格键
  8. 输入新视频的名称,例如my_new_video.ts。请注意,格式必须与原始视频相同,否则可能需要很长时间进行转换甚至失败!
  9. 按下Enter。等待终端完成合并过程,并享受观看视频的乐趣!

4
这项工作原本运行良好,直到聪明的HTML / JS专家开始完全避免使用“*.m3u8”格式。糟糕! - Gwyneth Llewelyn

4

我在这里找到了一个答案(链接),想引用它,因为它看起来比被接受的答案更简洁:

function blobToDataURL(blob, callback) {
  var fileReader = new FileReader();
  fileReader.onload = function(e) {callback(e.target.result);}
  fileReader.readAsDataURL(blob);
}

-2

这里是解决方案:

        let blob = new Blob(chunks, { 'type' : 'video/mp4;' });
        let videoURL = window.URL.createObjectURL(blob);
        const blobF = await fetch(videoURL).then(res => res.blob())

关于 MIME 类型,不正确的是 video/mp4,正确的应该是 octet/stream - KingRider

-2

我来晚了。

如果你想下载内容,现在可以简单地使用 fetch

fetch(blobURL)
  .then(res => res.blob())
  .then(blob => /*do what you want with the blob here*/)

3
我一直在尝试使用你的代码(参考了 https://dev59.com/lGct5IYBdhLWcg3wuPq6#58021822),但是显然,`fetch()`无法获取 blob:https://example.com/123e4567-e89b-12d3-a456-426614174000 这样的 URL。我正在进一步调查…… - Gwyneth Llewelyn
2
@GwynethLlewelyn 你找到任何解决方案了吗? - Ghanshyam Baravaliya

-5

正如先前的回答所述,没有办法将其解码为URL,即使您尝试从Chrome开发工具面板中查看它,URL也可能仍然被编码为blob。

但是,可以获取数据,另一种获取数据的方法是将其放入锚点并直接下载。

<a href="blob:http://example.com/xxxx-xxxx-xxxx-xxxx" download>download</a>

将这段代码插入到包含 Blob URL 的页面中,然后点击按钮,即可获取内容。
另一种方法是通过代理服务器拦截 AJAX 调用,然后您就可以查看真实的图像 URL。

<a href="blob:http://example.com/xxxx-xxxx-xxxx-xxxx" download="abc.txt">下载</a>。它应该可以工作。当它点击href时,它会将blob重命名为abc.txt并下载。 - Satish Patro
3
为什么会有负评?你是否真的尝试过我所说的内容? - ospider
我没有投反对票。我来到这里了。而且,我认为它会起作用。我有一点支持这个。 - Satish Patro
4
不确定为什么会被踩,但这肯定是一种简单直接的方式。(话虽如此,我总是在Linux上使用Chrome 83.0.4103.97时遇到“失败 - 网络错误”的问题。) - toraritte
3
很有趣。我打开了DevTools并添加了一些带有链接的HTML。它确实做了一些事情:它出现在页面上,并且你可以点击下载它,但是就像@toraritte所说的那样,我也收到了“失败-网络错误”的提示。 - Gwyneth Llewelyn

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