オブジェクトのURLからファイルまたはBLOBを取得する方法


127

ユーザーがドラッグ&ドロップやその他の方法で画像をページにロードできるようにしています。画像がドロップURL.createObjectURLされると、画像を表示するためにオブジェクトURLに変換するために使用しています。私はそれを再利用するので、私はそのURLを取り消すことはしません。

それが作成するための時間が来るときので、FormData私は彼らがそれで、これらのイメージのいずれかでフォームをアップロードできるようにすることができるようにオブジェクトを、いくつかの私は、その後にそのオブジェクトのURLの背中を逆にすることができます方法はありBlobか、File私はその後、Aにそれを追加することができるようには、FormDataオブジェクト?


前の2つのコメントについては気にしないでください。必要なのはXMLHttpRequest、Blob URLにを送信することだけです。
ゲンケフ2012

2
単純に元のファイルオブジェクトをどこかに保存し、オブジェクトのURLを使用してそれらを表示し、フォームの送信時に元のファイルを使用するのはなぜですか。
user764754 2017年

@ user764754ユーザーがアップロードするファイルのURLを取得しようとすると「C:\ fakepath」と表示されるため
Malcolm Salvador

回答:


86

最新のソリューション:

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

URLは、オブジェクトURLまたは通常のURLです。


3
いいね。ES5によってこのようなことがより簡単になることをうれしく思います。
BrianFreud

11
そして、直接promiseからファイルを取得したい場合は、次のようにファイルを生成できます。 let file = await fetch(url).then(r => r.blob()).then(blobFile => new File([blobFile], "fileNameGoesHere", { type: "image/png" })
dbakiu

3
残念ながら、このソリューションはChromeでは機能しません。ブラウザはこのURLを読み込めません。
ウォルドガイスト

Waldgeist、それをcreateObjectUrl()でラップしましたか?
マットフレッチャー

73

上記のコメントでgengkevが言及しているように、これを行うには、非同期の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();

更新(2018):ES5を安全に使用できる状況について、Joeは以下に簡単なES5ベースの回答を用意しています。


19
ときあなたは今まで持っていますいるObjectURL現在のドメインとスコープにローカルではないでしょうか?
BrianFreud 2014年

4
私は上記と同じようにしましたが、xhrで404が見つかりませんでした。どうしたの?
albert yu

一部のブラウザ(古いIEを読む...)のでご注意ください、あなたはそれらを参照してくださいポスト処理するために必要がある場合stackoverflow.com/questions/17657184/...
mraxus

4
@BrianFreud「現在のドメインとスコープにローカルではないobjectURLがあるのはいつですか?」私の場合、Amazon S3 blobに別のファイル名を付けようとしています。これは現在、拡張子のないS3の「guid」です。したがって、私の場合は、クロスドメインコールを使用しています。
ワーグナーベルトリーニジュニア

6
「オブジェクトURLは、ディスク上のファイルを指すURLです。」ObjectURLは、定義上ローカルのみです。
BrianFreud 2016年

12

多分誰かがこれが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)
         }

    })

1
これはクロスドメインリクエストで機能しますか?Twitter動画にはblob URLがあります。blob URLが指しているblobオブジェクトを収集できるようにする必要があります。ブラウザでフェッチAPIを使用しているため、このエラーが発生します– Refused to connect to 'blob:https://twitter.com/9e00aec3-6729-42fb-b5a7-01f50be302fa' because it violates the following Content Security Policy directive: "connect-src 。私が間違っているかもしれない/理解できないかもしれないことのヒントを教えてください。
gdadsriver 2018年

このワンライナーを使用して、blobをデータプロパティとして結果を取得できました。const result = await axios.get(url、{responseType: "blob"});
Noah Stahl


4

以下のようなフェッチの使用例:

 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);
})

Chromeコンソールに貼り付けてテストできます。「sample.xlsx」でダウンロードしたファイルそれが役立つことを願っています!


OPは、ブロブURLを実際のファイル/ブロブに変換するのではなく、逆に変換することを求めたと思います。
Abhishek Ghosh

3

残念ながら、@ BrianFreudの回答は私のニーズに適合しません。少し異なるニーズがあり、@ BrianFreudの質問に対する回答ではないことはわかっていますが、多くの人が同じニーズを持ってここに来たので、ここには残しません。「URLからファイルまたはblobを取得する方法」のようなものが必要でしたが、現在の正しい答えはクロスドメインではないため、私のニーズに合いません。

Amazon S3 / Azure Storageの画像を使用するウェブサイトがあり、そこにuniqueidentifiersで名前が付けられたオブジェクトを保存しています。

サンプル:http://****.blob.core.windows.net/systemimages/bf142dc9-0185-4aee-a3f4-1e5e95a09bcf

この画像の一部は、システムインターフェースからダウンロードする必要があります。このトラフィックがHTTPサーバーを通過しないようにするため、このオブジェクトにアクセスするためのセキュリティは必要ないため(ドメインフィルタリングを除く)、ユーザーのブラウザーに直接リクエストを送信し、ローカル処理を使用してファイルに実際の名前を付け、拡張。

それを達成するために、私はヘンリーアルガスからのこの素晴らしい記事を使用しました:http ://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

1.最初のステップ:バイナリサポートをjqueryに追加する

/**
*
* jquery.binarytransport.js
*
* @description. jQuery ajax transport for making binary data type requests.
* @version 1.0 
* @author Henry Algus <henryalgus@gmail.com>
*
*/

// 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. 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);
    });
}

これで、作成したBlobを好きなように使用できます。私の場合は、ディスクに保存します。

3.オプション:FileSaverを使用してユーザーのコンピューターにファイルを保存する

FileSaver.jsを使用して、ダウンロードしたファイルをディスクに保存しました。それを達成する必要がある場合は、次のJavaScriptライブラリを使用してください。

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

これは、より具体的なニーズを持つ他の人を助けることを期待しています。


1
ObjectURLは定義上ローカルです。オブジェクトURLは、ディスク上のファイルを指すURLです。クロスドメインのobjectURLなどがないことを考えると、2つの異なる概念を組み合わせて、与えられたソリューションを使用して問題を解決していることになります。
BrianFreud 2016年

1
@BrianFreud私はこの質問の答えではないことを理解しました。しかし、「URLからファイルまたはBLOBを取得するにはどうすればよいですか?」という少し異なる質問の答えを探してここに来て以来、私はそれでも良い答えだと思います。自分の回答を確認すると、「クロスドメインリクエストの場合は機能しません」について10の賛成票があります。'。それで、10人以上がそれを求めてここに来ました。私はそれをここに残すことにしました。
Wagner Bertolini Junior 2016

問題は、あなたの答えが故意にこの質問に答えないことです。通常のURLとオブジェクトURLは2つのまったく異なるものです。「クロスドメインリクエストの場合は機能しません。」に関する賛成票の数について、ここで文字通りそれが不可能である理由を説明し、通常のURLの回答が表示される場所を指摘するほうがいいと思いませんか。ここで通常のURLとオブジェクトURLを混同して混乱させるよりも
BrianFreud 2017

@BrianFreudが私の回答の編集を提案してください。私は主題について勉強します、多分私は「objectURL」対「object URL」が何であるかを誤解しました...英語は私の母国語ではありません。より良い答えを与えるために私は主題について調査します。しかし、それは何か違うものを探してここに来る他の人たちだと思います。ここに到達するために「objectURL」を検索しませんでした。それが以前の私のポイントでした。しかし、私もあなたを得ました。
ワグナーベルトリーニジュニア

2

とにかくキャンバスにファイルを表示する場合は、キャンバスのコンテンツを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);
})

2
実際には同じ元のファイルが返されるわけではないことに注意してください。その場で新しい画像ファイルを作成しています。数年前にそれを最後にテストしたとき、少なくともChromeでは、新しい画像ファイルはまったく圧縮されていないことがわかりました。
BrianFreud 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.