用户登录
用户注册

分享至

使用 Ajax 和 PHP $_FILES 从 Canvas 元素发送图像

  • 作者: 张井空
  • 来源: 51数据库
  • 2022-12-08

问题描述

我需要能够将图像和一些表单字段从客户端画布元素发送到 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.

软件
前端设计
程序设计
Java相关