Tim Schmidt Tim Schmidt - 9 months ago 69
HTML Question

PHP+JS: How to do Fileuploads in HTML Form as Content-Type Multipart (via JS)?

  1. Having an HTML Form that is submittet via POST (user clicking the
    submit button).

  2. Furthermore having an image that is read via Javascript of a canvas
    object (getImageData()).


How to "inject" this image data into the HTML Form, so that it gets uploaded as Content-Type:multipart/form-data and can be processed via the existing PHP Frameworks Data Extraction Logic?

Example from a
<input type="file"
upload captured with CHrome in a POST request => it should look like this

Content-Disposition: form-data; name="images"; filename="fooimage.png"
Content-Type: image/png

I know how to uploed it in a seperate request (via ajax, seperate from the form). I know how to upload it as base64 Data an process it manually in the form.

But I do not know how to send the Image Data along the exiting Form so that it looks for the PHP Serverside Scripts exactly the same as an image that is send via
<input type="file"...

Reason: Symphony (FileUpload Object) checks if a file is uploaded via the POST Form and fails if I manulally instanciate the object with the data.

So the best solution would be (in regards to a lot of other things, like testing, avoiding unnecessary logik), if the data would be passed the same as a regular form upload. How to do this?


Answer Source

You can use a FormData object to get the values of your form, and then append a blob version of your canvas into the FormData.

This blob will be seen as a file by the server.

Unfortunately, all browsers still don't support the native canvas.toBlob() method, and even worth, all implementations are not the same.
All major browsers now support the toBlob method, and you can find a polyfill on mdn for older browsers.

// the function to create and send our FormData
var send = function(form, url, canvas, filename, type, quality, callback) {

    var formData = form ? new FormData(form) : new FormData();
    formData.append('file', blob, filename);

    var xhr = new XMLHttpRequest();
    xhr.onload = callback;
    xhr.open('POST', url);

    }, type, quality);

// How to use it //

var form = document.querySelector('form'),   // the form to construct the FormData, can be null or undefined to send only the image
  url = 'http://example.com/upload.php',     // required, the url where we'll send it
  canvas = document.querySelector('canvas'), // required, the canvas to send
  filename = (new Date()).getTime() + '.jpg',// required, a filename
  type = 'image/jpeg',                       // optional, the algorithm to encode the canvas. If omitted defaults to 'image/png'
  quality = .5,                              // optional, if the type is set to jpeg, 0-1 parameter that sets the quality of the encoding
  callback = function(e) {console.log(this.response);}; // optional, a callback once the xhr finished

send(form, url, canvas, filename, type, quality, callback);

PHP side would then be :

if ( isset( $_FILES["file"] ) ){
    $dir = 'some/dir/';
    $blob = file_get_contents($_FILES["file"]['tmp_name']);
    file_put_contents($dir.$_FILES["file"]["name"], $blob);