PHP+JS:如何将 HTML 表单中的文件上传为 Content-Type Multipart(通过 JS)?

  1. 拥有一个通过 POST 提交的 HTML 表单(用户单击提交按钮).

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

此外,还有一张通过画布的 Javascript 读取的图像对象 (getImageData()).

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

问题:

如何将这些图像数据注入"到 HTML 表单中,使其作为 Content-Type:multipart/form-data 上传并可以通过现有的 PHP 框架数据提取逻辑进行处理?

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?

示例来自 <input type="file" 在 POST 请求中使用 CHrome 捕获的上传 => 它应该如下所示

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

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

问题:我知道如何在单独的请求中上传它(通过 ajax,与表单分开).我知道如何将它作为 base64 数据上传并在表单中手动处理它.

Problem: 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.

但我不知道如何沿着现有表单发送图像数据,以便它查找与通过 <input type="file" 发送的图像完全相同的 PHP 服务器端脚本..

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

原因:Symphony(FileUpload 对象)检查文件是否通过 POST 表单上传,如果我使用数据手动实例化对象,则会失败.
所以最好的解决方案是(关于很多其他事情,比如测试,避免不必要的逻辑),如果数据将像常规表单上传一样传递.如何做到这一点?

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?

谢谢!

推荐答案

你可以使用 FormData 对象来获取表单的值,然后将画布的 blob 版本附加到 FormData.

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.

这个 blob 将被服务器视为一个文件.

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

很遗憾,所有浏览器仍然不支持原生 canvas.toBlob() 方法,甚至值得,所有 实现不一样.
现在所有主流浏览器都支持 toBlob 方法,你可以找到 mdn 上的一个 polyfill,适用于旧版浏览器.

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

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

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

    }, 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 方面将是:

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

相关文章