Trying to Pass ToDataURL with over 524288 bytes Using Input Type Text
Try sending canvas
as Blob
at javascript
; use fopen()
with php://input
as parameter to read Blob
, stream_copy_to_stream
or file_get_contents()
, file_put_contents()
to process file at php
See HTMLCanvasElement.toBlob()
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function (callback, type, quality) {
var binStr = atob( this.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'} ) );
}
});
}
Beyond $_POST, $_GET and $_FILE: Working with Blob in JavaScript and PHP
<?php
// choose a filename
$filename = "hello.json";
// the Blob will be in the input stream, so we use php://input
$input = fopen('php://input', 'rb');
$file = fopen($filename, 'wb');
// Note: we don't need open and stream to stream, we could've used file_get_contents and file_put_contents
stream_copy_to_stream($input, $file);
fclose($input);
fclose($file);
?>
How to replace a file input's content by the result of canvas.toDataURL?
It seems we cannot modify the <input type="file">
, but we can add the data to another text field (as advised by @PatrickEvans) or an <input type="hidden">
:
function doit() { var file = document.getElementById('file').files[0], canvas = document.getElementById('canvas'), hidden = document.getElementById('hidden'), ctx = canvas.getContext("2d"), img = document.createElement("img"), reader = new FileReader(); reader.onload = function(e) { img.src = e.target.result; } img.onload = function () { ctx.drawImage(img, 0, 0); hidden.value = canvas.toDataURL("image/jpeg", 0.5); } reader.readAsDataURL(file);}
<input type="file" onchange="doit();" id="file" />
<form action="/upload" method="post"><input type="hidden" id="hidden" /><input type="submit" /></form>
<canvas id="canvas" style="display: none" />
How I put the canvas content as a file in a input type file
The best is still to send files through a FormData and AJAX.
But since it seems it's for personal use, and that you already have something working with a <form>, you can probably use what is still an hack exposed in this answer of mine. Beware this still works only in latest Chromium and Geckos browsers (no Webkit support, which means no iOS support).
So the step by step is,
- draw on your canvas.
- export it to a Blob using the
HTMLCanvasElement.toBlob()
method. - build a File from this Blob
- build a DataTransfer object
- append the File to the DataTransfer's
items
list - set the
.files
property of your <input type="file"> to the DataTransfer's.files
// draw on the canvas
const canvas = document.createElement( "canvas" );
const ctx = canvas.getContext( "2d" );
ctx.fillStyle = "red";
ctx.fillRect( 20, 20, 260, 110 );
// convert to Blob (async)
canvas.toBlob( (blob) => {
const file = new File( [ blob ], "mycanvas.png" );
const dT = new DataTransfer();
dT.items.add( file );
document.querySelector( "input" ).files = dT.files;
} );
// to prove the image is there
document.querySelector( "#test" ).onclick = (evt) => {
const file = document.querySelector( "input" ).files[ 0 ];
document.body.appendChild( new Image() )
.src = URL.createObjectURL( file );
};
<form method="POST">
<input type="file" name="file"><br>
<button>submit</button> (check your dev tools network panel to see the File is sent)
</form>
<br>
<button id="test">
load input's content as image
</button>
Sending canvas.toDataURL() as FormData
To send binary data in a POST request, you want to use a Blob. A Blob represents raw binary data. To get a Blob of a Canvas, you can use the toBlob method.
Once you have the Blob instance, you can add the Blob to the FormData using the append method. The append method accepts Blob instances as the second argument. You can even pass an optional third argument to append to specify the filename to send with the Blob to the server.
The blob will be received on the server as file data.
An example of this in action:
const canvas = document.getElementById('my-canvas');
canvas.toBlob(function(blob) {
const formData = new FormData();
formData.append('my-file', blob, 'filename.png');
// Post via axios or other transport method
axios.post('/api/upload', formData);
});
Related Topics
How to Use Perl Libraries from PHP
Mysqli - Fetch_Array Error Call to a Member Function Fetch_Array() on a Non-Object MySQLi
How Does SQL-Injection Work and How to Protect Against It
Why Is My Number Value Changing Using Number_Format()
PHP - Add Two Hours to Date Variable
When and Where Should I Use Session_Start
Distance Calculations in MySQL Queries
Checking If 2 Arrays Have at Least 1 Equal Value
How to Fix 'Creating Default Object from Empty Value' Warning in PHP
How to Bind Decimal/Double/Float Values with Pdo in PHP
How to Convert PHP Regex to JavaScript Regex
Change Innerhtml of a PHP Domelement
Get Number of Rows Matched by Update Query with PHP MySQLi
Explode a Paragraph into Sentences in PHP