Intereting Posts
Интеграция jQuery fullcalendar в PHP-сайт Zend-приложение и bootstrap как не mvc PHP / CodeIgniter – установка переменных в __construct (), но они недоступны из других функций mod_rewrite с вопросительными знаками и амперсандами (с PHP) Laravel – порядок промежуточного ПО (приоритет промежуточного ПО). Мульти-арендатор с использованием Postgres Laravel 5 Middleware «Владелец»? Сохранять данные в автономном режиме до публикации PHP игнорирует сертификаты ssl при подключении к MySql PHP – арифметические операции с использованием строк как операторов Разбирайте XML с помощью пространства имен с помощью SimpleXML «Установить имена» и mysqli_set_charset – кроме того, что они влияют на mysqli_escape_string, они идентичны? Как я могу сортировать id и sub_id в порядке убывания? Как защитить / закодировать Javascript POST-запросы Экзотические имена методов, констант, переменных и полей – ошибка или функция? Как установить клиентскую библиотеку PostgreSQL для PHP в Windows с включенным SSL

Как сохранить холст HTML5 как изображение на сервере?

Я работаю над генеративным арт-проектом, где я хотел бы разрешить пользователям сохранять полученные изображения из алгоритма. Общая идея:

  • Создайте изображение на холсте HTML5 с помощью генеративного алгоритма
  • Когда изображение будет завершено, разрешите пользователям сохранять холст в качестве файла изображения на сервере
  • Разрешить пользователю либо загружать изображение, либо добавлять его в галерею частей, созданных с использованием алгоритма.

Тем не менее, я застрял на втором шаге. После некоторой помощи от 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); } ?> 

Но это, похоже, ничего не делает.

Больше Googling превращает это сообщение в блоге , основанное на предыдущем уроке. Не совсем по-другому, но, возможно, стоит попробовать:

 $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).

Есть ли что-то действительно очевидное, что я делаю неправильно? Путь, где я храню свой файл, доступен для записи, поэтому это не проблема, но ничего похожего не происходит, и я не уверен, как отлаживать это.

редактировать

После ссылки Сальвидора Дали я изменил запрос 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 кБ. Тем не менее, я все еще не могу открыть его и, похоже, не отформатирован как изображение.

Вот пример того, как добиться того, что вам нужно:

1) Нарисуйте что-нибудь (взято из учебника по холсту )

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

2) Преобразование изображения холста в формат URL (base64)

 var dataURL = canvas.toDataURL(); 

3) Отправьте его на свой сервер через 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. }); 

3) Сохраните base64 на своем сервере в качестве изображения (вот как это сделать в PHP , те же идеи на каждом языке. Сфера сервера в PHP можно найти здесь ):

Я играл с этим две недели назад, это очень просто. Единственная проблема заключается в том, что все учебники просто говорят о сохранении изображения локально. Вот как я это сделал:

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']); ?> 

Если вы хотите сохранить данные, полученные из функции canvas.toDataURL() Javascript, вам нужно преобразовать пробелы в плюсы. Если вы этого не сделаете, декодированные данные будут повреждены:

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

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

Я думаю, вы должны преобразовать изображение в base64 в изображение с помощью blob, потому что, когда вы используете образ base64, требуется много строк журнала или много строк будет отправлено на сервер. С blob это только файл. Вы можете использовать этот код ниже:

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

И код холста здесь:

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

После этого вы можете использовать ajax с формой:

  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 

Этот код использует синтаксис CoffeeScript.

В дополнение к ответу Сальвадора Дали:

на стороне сервера не забывайте, что данные поступают в формате base64. Это важно, потому что на некоторых языках программирования вам нужно сказать, что эту строку следует считать байтами, а не простой строкой Unicode.

В противном случае декодирование не будет работать: изображение будет сохранено, но это будет нечитаемый файл.

Отправить изображение холста в PHP:

 var photo = canvas.toDataURL('image/jpeg'); $.ajax({ method: 'POST', url: 'photo_upload.php', data: { photo: photo } }); 

Вот скрипт PHP:
photo_upload.php

 <?php $data = $_POST['photo']; list($type, $data) = explode(';', $data); list(, $data) = explode(',', $data); $data = base64_decode($data); mkdir($_SERVER['DOCUMENT_ROOT'] . "/photos"); file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/photos/".time().'.png', $data); die; ?>