source

오브젝트 URL에서 파일 또는 BLOB를 가져오려면 어떻게 해야 합니까?

gigabyte 2023. 1. 12. 22:06
반응형

오브젝트 URL에서 파일 또는 BLOB를 가져오려면 어떻게 해야 합니까?

드래그 앤 드롭 등의 방법으로 이미지를 페이지에 로드할 수 있도록 하고 있습니다.할 때, ★★★★★★★★★★★★★★★★★★★★★★를 사용하고 있습니다.URL.createObjectURL브로로 URL 。은 취소하지 않습니다.

ㅇㅇㅇ를 때, ㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇ.FormData 할 수 수 요?Blob ★★★★★★★★★★★★★★★★★」File 수 요.FormData 오브젝트?

최신 솔루션:

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

url은 오브젝트 URL 또는 일반 URL일 수 있습니다.

위의 코멘트에서 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에 기초한 답변을 아래에 제시합니다.

리액트/노드/Axios를 사용할 때 유용하게 사용할 수 있습니다. 이미지 하였습니다.Cloudinary 이미지 업로드 기능은 다음과 .react-dropzone를 클릭합니다.

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

    })

다음과 같이 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);
})

Chrome 콘솔에 붙여넣어 테스트할 수 있습니다.'샘플'이 포함된 다운로드 파일이 있습니다.xlsx' 도움이 되었으면 좋겠네요!

blob URL을 다시 가져올 때의 문제는 Blob의 데이터 전체 복사본이 생성되기 때문에 메모리에 한 번만 저장하는 것이 아니라 두 번 가지게 된다는 것입니다.Big Blobs에서는 메모리 사용량이 매우 빠르게 증가할 수 있습니다.

File API가 현재 링크되어 있는 Blobs에 대한 액세스를 제공하지 않는 것은 유감스러운 일입니다.그들은 웹 작성자가 작성 시 Blob을 저장해야 한다고 생각했습니다.이것은 사실입니다.

여기서 가장 좋은 것은 BLOB:// URL을 만들 때 사용한 개체를 저장하는 것입니다.

이렇게 하면 Blob이 Garbage Collected가 되지 않을 것 같다면, BLOB:// URL도 취소될 때까지 수집됩니다.그러니 그 블롭에 대한 포인터를 가져도 아무것도 변하지 않을 거야

그러나 blob:// URI 작성에 책임이 없는 사용자(예를 들어 라이브러리가 작성했기 때문에)의 경우 기본 URL.createObject를 덮어쓰면 API 구멍을 채울 수 있습니다.URLURL.revoke Object전달된 객체에 대한 참조를 저장하기 위한 URL 메서드.

blob://URI를 생성하는 코드가 호출되기 전에 이 함수를 호출해야 합니다.

// Adds an URL.getFromObjectURL( <blob:// URI> ) method
// returns the original object (<Blob> or <MediaSource>) the URI points to or null
(() => {
  // overrides URL methods to be able to retrieve the original blobs later on
  const old_create = URL.createObjectURL;
  const old_revoke = URL.revokeObjectURL;
  Object.defineProperty(URL, 'createObjectURL', {
    get: () => storeAndCreate
  });
  Object.defineProperty(URL, 'revokeObjectURL', {
    get: () => forgetAndRevoke
  });
  Object.defineProperty(URL, 'getFromObjectURL', {
    get: () => getBlob
  });
  const dict = {};

  function storeAndCreate(blob) {
    const url = old_create(blob); // let it throw if it has to
    dict[url] = blob;
    return url
  }

  function forgetAndRevoke(url) {
    old_revoke(url);
    try {
      if(new URL(url).protocol === 'blob:') {
        delete dict[url];
      }
    } catch(e){}
  }

  function getBlob(url) {
    return dict[url] || null;
  }
})();

//  Usage:
const blob = new Blob( ["foo"] );
const url = URL.createObjectURL( blob );
console.log( url );
const retrieved = URL.getFromObjectURL( url );
console.log( "retrieved Blob is Same Object?", retrieved === blob );
fetch( url ).then( (resp) => resp.blob() )
  .then( (fetched) => console.log( "fetched Blob is Same Object?", fetched === blob ) );

또 다른 장점은 Media Source 오브젝트도 취득할 수 있지만 이 경우 취득 솔루션이 에러에 불과하다는 점입니다.

BlobBuilder가 Chrome에서 작동하지 않으므로 다음을 사용해야 함을 나타내는 XHR 요청에서 BLOB 데이터 가져오기를 참조하십시오.

xhr.responseType = 'arraybuffer';

안타깝게도 @BrianFreud의 답변은 제 요구와 맞지 않고, 저는 조금 다른 요구를 가지고 있었습니다.그리고 그것이 @BrianFreud의 질문에 대한 답변은 아니라는 것을 알고 있습니다만, 많은 분들이 저의 같은 요구를 가지고 와주셨기 때문에, 저는 여기에 남겨두고 있습니다.'URL에서 파일이나 BLOB를 가져오는 방법' 같은 것이 필요했는데, 현재 정답은 교차 도메인이 아니기 때문에 제 요구에 맞지 않습니다.

Amazon S3/Azure Storage에서 이미지를 소비하는 웹 사이트가 있으며, 고유 식별자로 명명된 개체를 저장합니다.

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

이 이미지 중 일부는 시스템인터페이스에서 다운로드해야 합니다.이 트래픽이 HTTP 서버를 통과하지 않도록 하기 위해 이 오브젝트는 (도메인 필터링을 제외하고) 보안에 액세스할 필요가 없기 때문에 사용자의 브라우저에서 직접 요청을 하고 로컬 처리를 사용하여 파일에 실제 이름과 확장자를 지정하기로 결정했습니다.

Henry Algus의 이 훌륭한 기사를 이용했습니다.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. 두 번째 단계 : 이 트랜스포트 타입을 사용하여 요청을 합니다.

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. 옵션: File Saver를 사용하여 사용자의 컴퓨터에 파일을 저장합니다.

FileSaver.js를 사용하여 다운로드한 파일을 디스크에 저장했습니다.필요한 경우 다음 javascript 라이브러리를 사용하십시오.

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

저는 이것이 좀 더 구체적인 요구를 가진 다른 사람들에게 도움이 될 것으로 기대합니다.

파일을 캔버스에 표시하면 캔버스 콘텐츠를 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);
})

@Kaiido answer에 이어 URL을 조작하지 않고 오버로드하는 또 다른 방법은 다음과 같이 URL 클래스를 확장하는 것입니다.

export class URLwithStore extends URL {
  static createObjectURL(blob) {
    const url = super.createObjectURL(blob);
    URLwithStore.store = { ...(URLwithStore.store ?? {}), [url]: blob };
    return url;
  }

  static getFromObjectURL(url) {
    return (URLwithStore.store ?? {})[url] ?? null;
  }

  static revokeObjectURL(url) {
    super.revokeObjectURL(url);
    if (
      new URL(url).protocol === "blob:" &&
      URLwithStore.store &&
      url in URLwithStore.store
    )
      delete URLwithStore.store[url];
  }
}

사용.

const blob = new Blob( ["foo"] );
const url = URLwithStore.createObjectURL( blob );
const retrieved = URLwithStore.getFromObjectURL( url );
console.log( "retrieved Blob is Same Object?", retrieved === blob );

언급URL : https://stackoverflow.com/questions/11876175/how-to-get-a-file-or-blob-from-an-object-url

반응형