[javascript] 데이터 URI를 파일로 변환 한 다음 FormData에 추가

Mozilla Hacks 사이트 것과 같은 HTML5 이미지 업 로더를 다시 구현하려고 시도 했지만 WebKit 브라우저에서 작동합니다. 작업의 일부는 canvas객체 에서 이미지 파일을 추출하여 업로드 할 FormData 객체에 추가하는 것 입니다.

문제는 동안이다 canvastoDataURL이미지 파일의 표현을 반환하는 기능의 FormData 객체는 파일을 수락하거나 물방울이에서 오브젝트 파일 API .

Mozilla 솔루션은 다음에서 Firefox 전용 기능을 사용했습니다 canvas.

var file = canvas.mozGetAsFile("foo.png");

… WebKit 브라우저에서는 사용할 수 없습니다. 내가 생각할 수있는 가장 좋은 해결책은 Data URI를 File 객체로 변환 할 수있는 방법을 찾는 것입니다.

가능합니까? 그렇지 않다면 대안이 있습니까?

감사.



답변

몇 가지를 가지고 놀다가 스스로 알아낼 수있었습니다.

우선, 이것은 dataURI를 Blob으로 변환합니다 :

function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}

여기에서 데이터를 파일로 업로드 할 수 있도록 양식에 데이터를 추가하는 것은 쉽습니다.

var dataURL = canvas.toDataURL('image/jpeg', 0.5);
var blob = dataURItoBlob(dataURL);
var fd = new FormData(document.forms[0]);
fd.append("canvasImage", blob);


답변

BlobBuilder 및 ArrayBuffer는 이제 더 이상 사용되지 않으며 Blob 생성자로 업데이트 된 최상위 주석 코드는 다음과 같습니다.

function dataURItoBlob(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
}


답변

이것은 iOS와 Safari에서 작동합니다.

Stoive의 ArrayBuffer 솔루션을 사용해야하지만 vava720에서 알 수 있듯이 BlobBuilder를 사용할 수 없으므로 다음은 두 가지의 매시업입니다.

function dataURItoBlob(dataURI) {
    var byteString = atob(dataURI.split(',')[1]);
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ab], { type: 'image/jpeg' });
}


답변

Firefox에는 canvas.toBlob ()canvas.mozGetAsFile () 메소드가 있습니다.

그러나 다른 브라우저는 그렇지 않습니다.

캔버스에서 dataurl을 가져온 다음 dataurl을 blob 객체로 변환 할 수 있습니다.

여기 내 dataURLtoBlob()기능이 있습니다. 매우 짧습니다.

function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], {type:mime});
}

이 함수를 FormData와 함께 사용하여 캔버스 또는 데이터 URL을 처리하십시오.

예를 들면 다음과 같습니다.

var dataurl = canvas.toDataURL('image/jpeg',0.8);
var blob = dataURLtoBlob(dataurl);
var fd = new FormData();
fd.append("myFile", blob, "thumb.jpg");

또한 HTMLCanvasElement.prototype.toBlob비 gecko 엔진 브라우저에 대한 메소드를 작성할 수 있습니다 .

if(!HTMLCanvasElement.prototype.toBlob){
    HTMLCanvasElement.prototype.toBlob = function(callback, type, encoderOptions){
        var dataurl = this.toDataURL(type, encoderOptions);
        var bstr = atob(dataurl.split(',')[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while(n--){
            u8arr[n] = bstr.charCodeAt(n);
        }
        var blob = new Blob([u8arr], {type: type});
        callback.call(this, blob);
    };
}

이제 canvas.toBlob()Firefox뿐만 아니라 모든 최신 브라우저에서 작동합니다. 예를 들면 다음과 같습니다.

canvas.toBlob(
    function(blob){
        var fd = new FormData();
        fd.append("myFile", blob, "thumb.jpg");
        //continue do something...
    },
    'image/jpeg',
    0.8
);


답변

내가 선호하는 방법은 canvas.toBlob ()입니다.

그러나 어쨌든 여기 fetch를 사용하여 base64를 blob으로 변환하는 또 다른 방법이 있습니다.

var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="

fetch(url)
.then(res => res.blob())
.then(blob => {
  var fd = new FormData()
  fd.append('image', blob, 'filename')

  console.log(blob)

  // Upload
  // fetch('upload', {method: 'POST', body: fd})
})


답변

@Stoive 및 @ vava720 덕분에 더 이상 사용되지 않는 BlobBuilder 및 ArrayBuffer를 사용하지 않고이 방법으로 두 가지를 결합했습니다.

function dataURItoBlob(dataURI) {
    'use strict'
    var byteString,
        mimestring

    if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
        byteString = atob(dataURI.split(',')[1])
    } else {
        byteString = decodeURI(dataURI.split(',')[1])
    }

    mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0]

    var content = new Array();
    for (var i = 0; i < byteString.length; i++) {
        content[i] = byteString.charCodeAt(i)
    }

    return new Blob([new Uint8Array(content)], {type: mimestring});
}


답변

진화하는 표준은 Mozilla가 추측 하기에 canvas.getAsFile ()이 아닌 canvas.toBlob () 인 것으로 보입니다.

아직 지원하는 브라우저가 없습니다. (

이 위대한 스레드에 감사드립니다!

또한 허용되는 답변을 시도하는 사람은 제한적이며 네임 스페이스 인 지원을 찾고 있으므로 BlobBuilder에주의해야합니다.

    var bb;
    try {
        bb = new BlobBuilder();
    } catch(e) {
        try {
            bb = new WebKitBlobBuilder();
        } catch(e) {
            bb = new MozBlobBuilder();
        }
    }

BlobBuilder에 다른 라이브러리의 폴리 필을 사용하고 있습니까?