问题描述
我需要能够将图像和一些表单字段从客户端画布元素发送到 PHP 脚本,以 $_POST 和 $_FILES 结尾.当我这样发送时:
I need to be able to send an image and some form fields from a client side canvas element to a PHP script, ending up in $_POST and $_FILES. When I send it like this:
<script type="text/javascript"> var img = canvas.toDataURL("image/png"); ... ajax.setRequestHeader('Content-Type', "multipart/form-data; boundary=" + boundary_str); var request_body = boundary + ' ' + 'Content-Disposition: form-data; name="formfield"' + ' ' + ' ' + formfield + ' ' + ' ' + boundary + ' ' + 'Content-Disposition: form-data; name="async-upload"; filename="' + "ajax_test64_2.png" + '"' + ' ' + 'Content-Type: image/png' + ' ' + ' ' + img + ' ' + boundary; ajax.send(request_body); </script>
$_POST 和 $_FILES 都返回填充,但 $_FILES 中的图像数据仍然需要像这样解码:
$_POST and $_FILES both come back populated, but the image data in $_FILES still needs decoding like this:
$loc = $_FILES['async-upload']['tmp_name']; $file = fopen($loc, 'rb'); $contents = fread($file, filesize($loc)); fclose($file); $filteredData=substr($contents, strpos($contents, ",")+1); $unencodedData=base64_decode($filteredData);
...为了将其保存为可读的 PNG.这不是一个选项,因为我正在尝试将图像传递给 Wordpress 的 media_handle_upload() 函数,该函数需要指向可读图像的 $_FILES 索引.我也无法相应地解码、保存和更改tmp_name",因为它违反了安全检查.
...in order to save it as a readable PNG. This isn't an option as I'm trying to pass the image to Wordpress's media_handle_upload() function, which requires an index to $_FILES pointing to a readable image. I also can't decode, save and alter 'tmp_name' accordingly, as it falls foul of security checks.
所以,我发现了这个:http://www.51sjk.com/Upload/Articles/1/0/338/338606_20221208100103946.html并尝试在客户端进行解码:
So, I found this: http://www.51sjk.com/Upload/Articles/1/0/338/338606_20221208100103946.html and tried to do the decode on the client side:
img_split = img.split(",",2)[1]; img_decoded = Base64.decode( img_split );
但由于某种原因,当它到达 PHP 时,我仍然没有得到一个可读的文件.所以问题是:为什么?"或我做错了什么?"或者这可能吗?":-)
but for some reason I still don't end up with a readable file when it gets to the PHP. So the question is: "Why?" or "What am I doing wrong?" or "Is this even possible?" :-)
非常感谢任何帮助!
谢谢,凯恩
推荐答案
以 Nathan 的出色回答为基础,我能够完善它,以便它仍然通过 jQuery.ajax.只需将其添加到 ajax 请求中:
Building on Nathan's excellent answer, I was able to finnagle it so that it is still going through jQuery.ajax. Just add this to the ajax request:
xhr: function () { var myXHR = new XMLHttpRequest(); if (myXHR.sendAsBinary == undefined) { myXHR.legacySend = myXHR.send; myXHR.sendAsBinary = function (string) { var bytes = Array.prototype.map.call(string, function (c) { return c.charCodeAt(0) & 0xff; }); this.legacySend(new Uint8Array(bytes).buffer); }; } myXHR.send = myXHR.sendAsBinary; return myXHR; },
基本上,您只需返回一个被覆盖的 xhr 对象,以便send"表示sendAsBinary".然后 jQuery 做正确的事.
Basically, you just return back an xhr object that is overriden so that "send" means "sendAsBinary". Then jQuery does the right thing.