HTML5 캔버스를 서버에 이미지로 저장하는 방법
저는 사용자가 알고리즘에서 생성된 이미지를 저장할 수 있도록 하는 생성 예술 프로젝트를 진행하고 있습니다.일반적인 생각은 다음과 같습니다.
- 생성 알고리즘을 사용하여 HTML5 캔버스에 이미지 생성
- 이미지가 완료되면 캔버스를 이미지 파일로 서버에 저장할 수 있습니다.
- 사용자가 이미지를 다운로드하거나 알고리즘을 사용하여 생성된 조각 갤러리에 추가할 수 있도록 합니다.
하지만, 저는 두 번째 단계에서 꼼짝할 수 없습니다.구글의 도움을 받은 후, 저는 이 블로그 포스트를 찾았습니다.그게 바로 제가 원하던 것 같았어요.
그 결과 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 코드의 (매우 큰) 문자열을 반환하며 데이터 파일은 약 140kB입니다.하지만 아직 열리지 않고 이미지 포맷이 되지 않은 것 같습니다.
필요한 것을 실현하는 방법의 예를 다음에 나타냅니다.
<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>
캔버스 이미지를 URL 형식(base64)으로 변환
// script var dataURL = canvas.toDataURL();
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.
});
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']);
?>
이미지를 base64로 변환한 후 blob으로 변환하여 서버로 보내야 할 것 같습니다.base64 이미지를 사용하면 많은 회선이 서버로 전송됩니다.BLOB의 경우 파일뿐입니다.
아래 코드를 사용할 수 있습니다.
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'
});
};
캔버스 코드는 다음과 같습니다.
const canvas = document.getElementById('canvas');
const file = dataURLtoBlob( canvas.toDataURL() );
그런 다음 Form과 함께 ajax를 사용할 수 있습니다.
const fd = new FormData;
fd.append('image', file);
$.ajax({
type: 'POST',
url: '/url-to-save',
data: fd,
processData: false,
contentType: false
});
커피 스크립트 구문의 코드:
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())
그런 다음 Form과 함께 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
캔버스 이미지를 PHP로 보내기:
var photo = canvas.toDataURL('image/jpeg');
$.ajax({
method: 'POST',
url: 'photo_upload.php',
data: {
photo: photo
}
});
PHP 크음음 php php php php php php php 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;
?>
저도 비슷한 작업을 한 적이 있어요.캔버스 Base64 인코딩 이미지 변환 필요Uint8Array Blob
.
function b64ToUint8Array(b64Image) {
var img = atob(b64Image.split(',')[1]);
var img_buffer = [];
var i = 0;
while (i < img.length) {
img_buffer.push(img.charCodeAt(i));
i++;
}
return new Uint8Array(img_buffer);
}
var b64Image = canvas.toDataURL('image/jpeg');
var u8Image = b64ToUint8Array(b64Image);
var formData = new FormData();
formData.append("image", new Blob([ u8Image ], {type: "image/jpg"}));
var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
xhr.send(formData);
canvas.toDataURL()
빈칸을 플러스로 변환해야 합니다.그렇게 하지 않으면 디코딩된 데이터가 손상됩니다.
<?php
$encodedData = str_replace(' ','+',$encodedData);
$decocedData = base64_decode($encodedData);
?>
http://php.net/manual/ro/function.base64-decode.php
Salvador Dali의 답변과 더불어:
데이터가 base64 문자열 형식으로 제공된다는 것을 잊지 마십시오.일부 프로그래밍 언어에서는 이 문자열이 단순한 유니코드 문자열이 아닌 바이트로 간주되어야 한다고 설명해야 하기 때문에 중요합니다.
그렇지 않으면 디코딩이 작동하지 않습니다.이미지는 저장되지만 읽을 수 없는 파일이 됩니다.
방금 imageCrop and Upload 기능을 만들었습니다.
https://www.npmjs.com/package/react-image-crop
ImagePreview(캔버스에서 잘라낸 이미지 렌더링)를 가져오려면
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
canvas.toBlob(function(blob){...}, 'image/jpeg', 0.95);
타입이 「BLOB」인합니다.image/jpeg
toDataURL
SAS URL을 사용하여 Azure Blob에 업로드하기 위한 구현
axios.post(azure_sas_url, image_in_blob, {
headers: {
'x-ms-blob-type': 'BlockBlob',
'Content-Type': 'image/jpeg'
}
})
언급URL : https://stackoverflow.com/questions/13198131/how-to-save-an-html5-canvas-as-an-image-on-a-server
'programing' 카테고리의 다른 글
MySQL에서 Maria로 WAMP 서버 전환DB (0) | 2022.10.29 |
---|---|
MariaDB/MySQL - 중첩된 객체의 키를 기반으로 JSON을 쿼리하는 방법 (0) | 2022.10.29 |
jQuery를 사용하여 페이지 로드 시 양식 입력 텍스트 필드에 초점을 맞추는 방법은 무엇입니까? (0) | 2022.10.29 |
.map()의 요소를 건너뛰는 방법 (0) | 2022.10.29 |
MariaDB JDBC 클라이언트로깅 (0) | 2022.10.29 |