web-dev-qa-db-ja.com

HTML5 Canvasをファイルに変換してアップロードしますか?

標準の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();

これにより、base64としてimage/pngが取得されます。

入力タイプファイルを使用した場合と同じ方法で、base64イメージをサーバーに送信するにはどうすればよいですか?

問題は、base64ファイルが、入力type = "file"内にあるファイルと同じタイプではないことです。

何らかの方法でサーバーのタイプが同じであるbase64を変換できますか?

52
confile

セキュリティ上の理由から、ファイル入力要素の値を直接設定することはできません。

ファイル入力要素を使用する場合:

  1. キャンバスから画像を作成します(完了しました)。
  2. その画像を新しいページに表示します。
  3. ユーザーにローカルドライブを右クリックして保存します。
  4. その後、ファイル入力要素を使用して、新しく作成されたファイルをアップロードできます。

あるいは、Ajaxを使用してPOSTキャンバスデータ:

あなたはブロブについて尋ねました:

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は通常、最新のブラウザーでサポートされています。

51
markE

キャンバス画像をbase64に変換してから、base64からバイナリに変換する必要があります。これは、.toDataURL()およびdataURItoBlob()を使用して行われます

それはかなり厄介なプロセスであり、いくつかのSO回答、さまざまなブログ投稿、チュートリアルをつなぎ合わせる必要がありました。

プロセスを順を追って説明できるチュートリアルを作成しました

Ateikのコメントへの応答として、ここに a fiddle があります。これは、元のリンクを表示できない場合に元の投稿を複製します。 ここでプロジェクトを分岐 にすることもできます。

多くのコードがありますが、私がやっていることの中核はキャンバス要素を取得することです:

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

コンテキストを2Dに設定します

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

Canvas => Base64 =>バイナリ

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を使用して)渡すことができるように、再度バイナリに変換する必要がありました。かなりクールなバイナリをツイートすることができ、Twitterはそれを画像に変換します。

25
Pixelomo

現在仕様中(17年4月現在、ほとんどサポートされていません)

Canvas.toBlob();

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

編集:

このリンクはポリフィル(言葉遣いからは遅いようです)を提供します。このコードは@pixelomo応答と大体同じですが、ネイティブtoBlobメソッドと同じAPIを使用します。

ToDataURLに基​​づく低パフォーマンスのポリフィル:

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
9
Danie A

別の解決策:var urlのデータを非表示フィールドに送信し、デコードしてサーバーに保存します。

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)
8
Ardine