programing

HTML5 캔버스를 업로드할 파일로 변환하시겠습니까?

telecom 2023. 9. 27. 16:55
반응형

HTML5 캔버스를 업로드할 파일로 변환하시겠습니까?

표준 HTML 파일 업로드는 다음과 같이 작동합니다.

<g:form method="post" accept-charset="utf-8" enctype="multipart/form-data"  
     name="form" url="someurl">

    <input type="file" name="file" id="file" />

</form>

저의 경우 html5 캔버스에 이미지를 로드하여 서버에 파일로 제출하고자 합니다.할 수 있습니다.

var canvas; // some canvas with an image
var url = canvas.toDataURL();

이미지/png를 base64로 표시합니다.

Base64 이미지를 입력타입 파일과 동일하게 서버로 전송하려면 어떻게 해야 합니까?

문제는 base64 파일이 입력 유형="file" 안에 있는 파일과 같은 유형이 아니라는 것입니다.

서버에 대해 타입이 동일한 base64를 어떻게든 변환할 수 있습니까?

보안상의 이유로 파일 입력 요소의 값을 직접 설정할 수 없습니다.

파일 입력 요소를 사용하려는 경우:

  1. 캔버스에서 이미지를 만듭니다(완료한 대로).
  2. 해당 이미지를 새 페이지에 표시합니다.
  3. 사용자가 로컬 드라이브에 마우스 오른쪽 단추로 클릭하여 저장하도록 합니다.
  4. 그러면 파일 입력 요소를 사용하여 새로 생성된 파일을 업로드할 수 있습니다.

또는 Ajax를 사용하여 캔버스 데이터를 게시할 수 있습니다.

블롭에 대해서 물어봤잖아요

var blobBin = atob(dataURL.split(',')[1]);
var array = [];
for(var i = 0; i < blobBin.length; i++) {
    array.push(blobBin.charCodeAt(i));
}
var file=new Blob([new Uint8Array(array)], {type: 'image/png'});


var formdata = new FormData();
formdata.append("myNewFileName", file);
$.ajax({
   url: "uploadFile.php",
   type: "POST",
   data: formdata,
   processData: false,
   contentType: false,
}).done(function(respond){
  alert(respond);
});

참고: blob은 일반적으로 최신 브라우저에서 지원됩니다.

캔버스 이미지를 베이스64로 변환한 다음 베이스64에서 바이너리로 변환해야 합니다.이 작업은 를 사용하여 수행됩니다..toDataURL()그리고.dataURItoBlob()

여러 SO 답변, 다양한 블로그 게시물 및 튜토리얼을 종합해야 하는 매우 어리석은 과정이었습니다.

이 과정을 안내하는 자습서를 만들었습니다.

Ateik의 의견에 응답하여 원본 링크를 보는 데 문제가 있을 경우 원본 게시물을 복제하는 fiddle을 제공합니다.여기서 제 프로젝트를 진행할 수도 있습니다.

많은 코드가 있지만 제가 하는 일의 핵심은 캔버스 요소를 사용하는 것입니다.

<canvas id="flatten" width="800" height="600"></canvas>

상황을 2D로 설정

var snap = document.getElementById('flatten');
var flatten = snap.getContext('2d');

캔버스 => 베이스64 => 바이너리

function postCanvasToURL() {
  // Convert canvas image to Base64
  var img = snap.toDataURL();
  // Convert Base64 image to binary
  var file = dataURItoBlob(img);
}

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

필요한 것이 그것뿐이라면 base64에서 멈출 수 있습니다. 제 경우에는 db를 사용하지 않고 twitter(OAuth 사용)에 데이터를 전달할 수 있도록 다시 binary로 변환해야 했습니다.당신은 꽤 멋진 바이너리를 트윗할 수 있고, 트위터는 그것을 다시 이미지로 변환할 것입니다.

이것이 결국 저에게 효과가 있었던 것입니다.

canvas.toBlob((blob) => {
  let file = new File([blob], "fileName.jpg", { type: "image/jpeg" })
}, 'image/jpeg');

현재 사양(17년 4월 현재 지원이 거의 없음)

Canvas.toBlob();

https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob

편집:

링크는 @pixelomo 응답과 거의 동일하지만 네이티브와 동일한 api를 사용하는 폴리필(문법에서 더 느린 것처럼 보이는)을 제공합니다.toBlob방법:

DataURL에 기반한 저성능 폴리필:

if (!HTMLCanvasElement.prototype.toBlob) {
  Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
    value: function (callback, type, quality) {
      var canvas = this;
      setTimeout(function() {

    var binStr = atob( canvas.toDataURL(type, quality).split(',')[1] ),
        len = binStr.length,
        arr = new Uint8Array(len);

    for (var i = 0; i < len; i++ ) {
      arr[i] = binStr.charCodeAt(i);
    }

    callback( new Blob( [arr], {type: type || 'image/png'} ) );

      });
    }
  });
}

이 방법으로 사용하려면:

canvas.toBlob(function(blob){...}, 'image/jpeg', 0.95); // JPEG at 95% quality

아니면

canvas.toBlob(function(blob){...}); // PNG

또 다른 해결책은 숨겨진 필드에 있는 varurl로 데이터를 보내고 해독하여 서버에 저장하는 것입니다.

Python Django의 예:

if form.is_valid():
    url = form.cleaned_data['url']
    url_decoded = b64decode(url.encode())        
    content = ContentFile(url_decoded) 
    your_model.model_field.save('image.png', content)
const canvas = document.querySelector("canvas");
canvas.toBlob(blob => {
  const file = new File([blob], "image.png");
});

전에는 아주 간단하게 했었습니다.

var formData = new FormData(),
    uploadedImageName = 'selfie.png';

canvas.toBlob(function (blob) {
    formData.append('user_picture', blob, uploadedImageName);
    $.ajax({
        data: formData,
        type: "POST",
        dataType: "JSON",
        url: '',
        processData: false,
        contentType: false,
    });
});

2023년 답변을 사용합니다.toBlobTypeScript:

const dataBlob = await new Promise<Blob | null>(
  (resolve) => canvas.toBlob(
    (blob) => resolve(blob),
    "image/png",
  )
);

언급URL : https://stackoverflow.com/questions/19032406/convert-html5-canvas-into-file-to-be-uploaded

반응형