290

ユーザーがアルゴリズムから得られた画像を保存できるようにしたいジェネレーティブアートプロジェクトに取り組んでいます。一般的な考え方は次のとおりです。

  • 生成アルゴリズムを使用して HTML5 Canvas に画像を作成する
  • 画像が完成したら、ユーザーがキャンバスを画像ファイルとしてサーバーに保存できるようにします
  • ユーザーが画像をダウンロードするか、アルゴリズムを使用して作成された作品のギャラリーに追加できるようにします。

しかし、私は2番目のステップで立ち往生しています。Google の助けを借りて、次のブログ投稿を見つけました。

JavaScriptコードにつながった:

function saveImage() {
  var canvasData = canvas.toDataURL("image/png");
  var ajax = new XMLHttpRequest();

  ajax.open("POST", "testSave.php", false);
  ajax.onreadystatechange = function() {
    console.log(ajax.responseText);
  }
  ajax.setRequestHeader("Content-Type", "application/upload");
  ajax.send("imgData=" + canvasData);
}

および対応する PHP (testSave.php):

<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
  $imageData = $GLOBALS['HTTP_RAW_POST_DATA'];
  $filteredData = substr($imageData, strpos($imageData, ",") + 1);
  $unencodedData = base64_decode($filteredData);
  $fp = fopen('/path/to/file.png', 'wb');

  fwrite($fp, $unencodedData);
  fclose($fp);
}
?>

しかし、これはまったく何もしていないようです。

さらにグーグルで検索すると、以前のチュートリアルに基づいたこのブログ投稿が表示されます。それほど違いはありませんが、おそらく試してみる価値があります。

$data = $_POST['imgData'];
$file = "/path/to/file.png";
$uri = substr($data,strpos($data, ",") + 1);

file_put_contents($file, base64_decode($uri));
echo $file;

これはファイルを作成しますが (yay)、ファイルが破損しており、何も含まれていないようです。また、空のように見えます (ファイル サイズ 0)。

私が間違っていることは本当に明らかですか?ファイルを保存しているパスは書き込み可能であるため、問題はありませんが、何も起こっていないようで、これをデバッグする方法がよくわかりません。

編集

Salvidor Dali のリンクに従って、AJAX リクエストを次のように変更しました。

function saveImage() {
  var canvasData = canvas.toDataURL("image/png");
  var xmlHttpReq = false;

  if (window.XMLHttpRequest) {
    ajax = new XMLHttpRequest();
  }
  else if (window.ActiveXObject) {
    ajax = new ActiveXObject("Microsoft.XMLHTTP");
  }

  ajax.open("POST", "testSave.php", false);
  ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  ajax.onreadystatechange = function() {
    console.log(ajax.responseText);
  }
  ajax.send("imgData=" + canvasData);
}

これで画像ファイルが作成され、空ではなくなりました! コンテンツタイプが重要であり、それを変更してx-www-form-urlencoded画像データを送信できるように思われます。

コンソールは base64 コードの (かなり大きな) 文字列を返し、データファイルは ~140 kB です。ただし、まだ開くことができず、画像としてフォーマットされていないようです。

4

8 に答える 8

267

必要なものを達成する方法の例を次に示します。

  1. 何かを描く( canvas チュートリアルから取得)

<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');

  // begin custom shape
  context.beginPath();
  context.moveTo(170, 80);
  context.bezierCurveTo(130, 100, 130, 150, 230, 150);
  context.bezierCurveTo(250, 180, 320, 180, 340, 150);
  context.bezierCurveTo(420, 150, 420, 120, 390, 100);
  context.bezierCurveTo(430, 40, 370, 30, 340, 50);
  context.bezierCurveTo(320, 5, 250, 20, 250, 50);
  context.bezierCurveTo(200, 5, 150, 20, 170, 80);

  // complete custom shape
  context.closePath();
  context.lineWidth = 5;
  context.fillStyle = '#8ED6FF';
  context.fill();
  context.strokeStyle = 'blue';
  context.stroke();
</script>

  1. キャンバス画像を URL 形式 (base64) に変換します

    var dataURL = canvas.toDataURL();

  2. Ajax経由でサーバーに送信します

    $.ajax({
      type: "POST",
      url: "script.php",
      data: { 
         imgBase64: dataURL
      }
    }).done(function(o) {
      console.log('saved'); 
      // If you want the file to be visible in the browser 
      // - please modify the callback in javascript. All you
      // need is to return the url to the file, you just saved 
      // and than put the image in your browser.
    });

  1. サーバーに base64 をイメージとして保存します( PHPでこれを行う方法は次のとおりです。すべての言語で同じ考え方があります。PHP のサーバー側は、ここにあります)。
于 2012-11-02T15:51:08.890 に答える
72

私はこれを2週間前にプレイしましたが、とてもシンプルです。唯一の問題は、すべてのチュートリアルが画像をローカルに保存することについて話しているだけであることです。これが私がやった方法です:

1) POST メソッドを使用できるようにフォームを設定しました。

2) 描画が完了したら、[保存] ボタンをクリックします。

3) ボタンをクリックすると、画像データを取得して隠しフィールドに入れます。その後、フォームを送信します。

document.getElementById('my_hidden').value = canvas.toDataURL('image/png');
document.forms["form1"].submit();

4) フォームが送信されると、次の小さな php スクリプトがあります。

<?php 
$upload_dir = somehow_get_upload_dir();  //implement this function yourself
$img = $_POST['my_hidden'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = $upload_dir."image_name.png";
$success = file_put_contents($file, $data);
header('Location: '.$_POST['return_url']);
?>
于 2012-11-02T16:09:23.577 に答える
29

I think you should convert the image to base64 and then to Blob and send it to the server. When you use base64 images, a lot of lines will be sent to server. With blob, it's only the file.

You can use this code bellow:

function dataURLtoBlob(dataURL) {
  let array, binary, i, len;
  binary = atob(dataURL.split(',')[1]);
  array = [];
  i = 0;
  len = binary.length;
  while (i < len) {
    array.push(binary.charCodeAt(i));
    i++;
  }
  return new Blob([new Uint8Array(array)], {
    type: 'image/png'
  });
};

And canvas code here:

const canvas = document.getElementById('canvas');
const file = dataURLtoBlob( canvas.toDataURL() );

After that you can use ajax with Form:

const fd = new FormData;

fd.append('image', file);

$.ajax({
  type: 'POST',
  url: '/url-to-save',
  data: fd,
  processData: false,
  contentType: false
});

The code in CoffeeScript syntax:

dataURLtoBlob = (dataURL) ->
  # Decode the dataURL
  binary = atob(dataURL.split(',')[1])
  # Create 8-bit unsigned array
  array = []
  i = 0
  while i < binary.length
    array.push binary.charCodeAt(i)
    i++
  # Return our Blob object
  new Blob([ new Uint8Array(array) ], type: 'image/png')

And canvas code here:

canvas = document.getElementById('canvas')
file = dataURLtoBlob(canvas.toDataURL())

After that you can use ajax with Form:

fd = new FormData
# Append our Canvas image file to the form data
fd.append 'image', file
$.ajax
  type: 'POST'
  url: '/url-to-save'
  data: fd
  processData: false
  contentType: false
于 2016-09-19T16:16:19.467 に答える
9

Javascript 関数から派生したデータを保存する場合はcanvas.toDataURL()、空白をプラスに変換する必要があります。そうしないと、デコードされたデータが破損します。

<?php
  $encodedData = str_replace(' ','+',$encodedData);
  $decocedData = base64_decode($encodedData);
?>

http://php.net/manual/ro/function.base64-decode.php

于 2014-02-06T05:15:04.350 に答える
4

サルバドール・ダリの答えに加えて:

サーバー側では、データが base64文字列形式であることを忘れないでください。一部のプログラミング言語では、この文字列を単純な Unicode 文字列ではなくバイトと見なす必要があることを明示的に示す必要があるため、これは重要です。

そうしないと、デコードが機能しません。画像は保存されますが、読み取り不能なファイルになります。

于 2014-10-24T15:27:20.443 に答える