Javascript 如何从对象 URL 获取文件或 blob?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11876175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 07:30:05  来源:igfitidea点击:

How to get a file or blob from an object URL?

javascripthtmlfileapiblobs

提问by BrianFreud

I am allowing the user to load images into a page via drag&drop and other methods. When an image is dropped, I'm using URL.createObjectURLto convert to an object URL to display the image. I am not revoking the url, as I do reuse it.

我允许用户通过拖放和其他方法将图像加载到页面中。放置图像时,我使用URL.createObjectURL转换为对象 URL 以显示图像。我不会撤销 url,因为我会重用它。

So, when it comes time to create a FormDataobject so I can allow them to upload a form with one of those images in it, is there some way I can then reverse that Object URL back into a Blobor Fileso I can then append it to a FormDataobject?

所以,当谈到时间来创建一个FormData对象,所以我可以让他们上传的形式,在它的形象之一,是有一些方法,然后我可以扭转这一目标URL回一个BlobFile这样我就可以再附加到一个FormData目的?

采纳答案by BrianFreud

Modern solution:

现代解决方案:

let blob = await fetch(url).then(r => r.blob());

The url can be an object url or a normal url.

url 可以是对象 url 或普通 url。

回答by BrianFreud

As gengkev alludes to in his comment above, it looks like the best/only way to do this is with an async xhr2 call:

正如 gengkev 在他上面的评论中提到的,看起来最好/唯一的方法是使用 async xhr2 调用:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'blob:http%3A//your.blob.url.here', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
  if (this.status == 200) {
    var myBlob = this.response;
    // myBlob is now the blob that the object URL pointed to.
  }
};
xhr.send();

Update (2018): For situations where ES5 can safely be used, Joe has a simpler ES5-based answer below.

更新(2018 年):对于可以安全使用 ES5 的情况,Joe 在下面有一个更简单的基于 ES5 的答案。

回答by spedy

Maybe someone finds this useful when working with React/Node/Axios. I used this for my Cloudinary image upload feature with react-dropzoneon the UI.

也许有人在使用 React/Node/Axios 时发现这很有用。我react-dropzone在 UI上将其用于 Cloudinary 图像上传功能。

    axios({
        method: 'get',
        url: file[0].preview, // blob url eg. blob:http://127.0.0.1:8000/e89c5d87-a634-4540-974c-30dc476825cc
        responseType: 'blob'
    }).then(function(response){
         var reader = new FileReader();
         reader.readAsDataURL(response.data); 
         reader.onloadend = function() {
             var base64data = reader.result;
             self.props.onMainImageDrop(base64data)
         }

    })

回答by user3843418

Using fetch for example like below:

使用 fetch 例如如下:

 fetch(<"yoururl">, {
    method: 'GET',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + <your access token if need>
    },
       })
.then((response) => response.blob())
.then((blob) => {
// 2. Create blob link to download
 const url = window.URL.createObjectURL(new Blob([blob]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', `sample.xlsx`);
 // 3. Append to html page
 document.body.appendChild(link);
 // 4. Force download
 link.click();
 // 5. Clean up and remove the link
 link.parentNode.removeChild(link);
})

You can paste in on Chrome console to test. the file with download with 'sample.xlsx' Hope it can help!

您可以粘贴到 Chrome 控制台进行测试。带有'sample.xlsx'的下载文件希望它可以帮助!

回答by Michel Floyd

See Getting BLOB data from XHR requestwhich points out that BlobBuilder doesn't work in Chrome so you need to use:

请参阅从 XHR 请求中获取 BLOB 数据,其中指出 BlobBuilder 在 Chrome 中不起作用,因此您需要使用:

xhr.responseType = 'arraybuffer';

回答by Wagner Bertolini Junior

Unfortunately @BrianFreud's answer doesn't fit my needs, I had a little different need, and I know that is not the answer for @BrianFreud's question, but I am leaving it here because a lot of persons got here with my same need. I needed something like 'How to get a file or blob from an URL?', and the current correct answer does not fit my needs because its not cross-domain.

不幸的是,@BrianFreud 的回答不符合我的需求,我有一点不同的需求,我知道这不是@BrianFreud 问题的答案,但我将它留在这里是因为很多人带着我同样的需求来到这里。我需要诸如“如何从 URL 获取文件或 blob?”之类的内容,而当前的正确答案不符合我的需求,因为它不是跨域的。

I have a website that consumes images from an Amazon S3/Azure Storage, and there I store objects named with uniqueidentifiers:

我有一个使用 Amazon S3/Azure 存储中的图像的网站,我在那里存储以 uniqueidentifiers 命名的对象:

sample: http://****.blob.core.windows.net/systemimages/bf142dc9-0185-4aee-a3f4-1e5e95a09bcf

示例:http://****.blob.core.windows.net/systemimages/bf142dc9-0185-4aee-a3f4-1e5e95a09bcf

Some of this images should be download from our system interface. To avoid passing this traffic through my HTTP server, since this objects does not require any security to be accessed (except by domain filtering), I decided to make a direct request on user's browser and use local processing to give the file a real name and extension.

其中一些图像应该从我们的系统界面下载。为了避免通过我的 HTTP 服务器传递这个流量,因为这个对象不需要任何安全性来访问(除了域过滤),我决定在用户​​的浏览器上直接请求并使用本地处理给文件一个真实的名字和延期。

To accomplish that I have used this great article from Henry Algus: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

为了实现这一点,我使用了 Henry Algus 的这篇很棒的文章:http: //www.henryalgus.com/reading-binary-files-using-jquery-ajax/

1. First step: Add binary support to jquery

1.第一步:为jquery添加二进制支持

/**
*
* jquery.binarytransport.js
*
* @description. jQuery ajax transport for making binary data type requests.
* @version 1.0 
* @author Henry Algus <[email protected]>
*
*/

// use this transport for "binary" data type
$.ajaxTransport("+binary", function (options, originalOptions, jqXHR) {
    // check for conditions and support for blob / arraybuffer response type
    if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob))))) {
        return {
            // create new XMLHttpRequest
            send: function (headers, callback) {
                // setup all variables
                var xhr = new XMLHttpRequest(),
        url = options.url,
        type = options.type,
        async = options.async || true,
        // blob or arraybuffer. Default is blob
        dataType = options.responseType || "blob",
        data = options.data || null,
        username = options.username || null,
        password = options.password || null;

                xhr.addEventListener('load', function () {
                    var data = {};
                    data[options.dataType] = xhr.response;
                    // make callback and send data
                    callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
                });

                xhr.open(type, url, async, username, password);

                // setup custom headers
                for (var i in headers) {
                    xhr.setRequestHeader(i, headers[i]);
                }

                xhr.responseType = dataType;
                xhr.send(data);
            },
            abort: function () {
                jqXHR.abort();
            }
        };
    }
});

2. Second step: Make a request using this transport type.

2. 第二步:使用此传输类型发出请求。

function downloadArt(url)
{
    $.ajax(url, {
        dataType: "binary",
        processData: false
    }).done(function (data) {
        // just my logic to name/create files
        var filename = url.substr(url.lastIndexOf('/') + 1) + '.png';
        var blob = new Blob([data], { type: 'image/png' });

        saveAs(blob, filename);
    });
}

Now you can use the Blob created as you want to, in my case I want to save it to disk.

现在您可以根据需要使用创建的 Blob,在我的情况下,我想将其保存到磁盘。

3. Optional: Save file on user's computer using FileSaver

3. 可选:使用 FileSaver 在用户计算机上保存文件

I have used FileSaver.js to save to disk the downloaded file, if you need to accomplish that, please use this javascript library:

我已经使用 FileSaver.js 将下载的文件保存到磁盘,如果你需要完成,请使用这个 javascript 库:

https://github.com/eligrey/FileSaver.js/

https://github.com/eligrey/FileSaver.js/

I expect this to help others with more specific needs.

我希望这可以帮助有更具体需求的其他人。

回答by Thilo

If you show the file in a canvas anyway you can also convert the canvas content to a blob object.

如果您无论如何都在画布中显示文件,您还可以将画布内容转换为 blob 对象。

canvas.toBlob(function(my_file){
  //.toBlob is only implemented in > FF18 but there is a polyfill 
  //for other browsers https://github.com/blueimp/JavaScript-Canvas-to-Blob
  var myBlob = (my_file);
})