gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 10:09:44 24 4
gpt4 key购买 nike

我需要能够将图像和一些表单字段从客户端 Canvas 元素发送到 PHP 脚本,最终以 $_POST 和 $_FILES 结束。当我这样发送时:

<script type="text/javascript">
var img = canvas.toDataURL("image/png");
...
ajax.setRequestHeader('Content-Type', "multipart/form-data; boundary=" + boundary_str);
var request_body = boundary + '\n'
+ 'Content-Disposition: form-data; name="formfield"' + '\n'
+ '\n'
+ formfield + '\n'
+ '\n'
+ boundary + '\n'
+ 'Content-Disposition: form-data; name="async-upload"; filename="'
+ "ajax_test64_2.png" + '"' + '\n'
+ 'Content-Type: image/png' + '\n'
+ '\n'
+ img
+ '\n'
+ boundary;
ajax.send(request_body);
</script>

$_POST 和 $_FILES 都已填充,但 $_FILES 中的图像数据仍然需要像这样解码:

$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”,因为它违反了安全检查。

所以,我发现了这个: http://www.webtoolkit.info/javascript-base64.html并尝试在客户端进行解码:

img_split = img.split(",",2)[1];
img_decoded = Base64.decode( img_split );

但由于某种原因,当它到达 PHP 时我仍然没有得到一个可读的文件。所以问题是:“为什么?”或“我做错了什么?”或“这可能吗?” :-)

非常感谢任何帮助!

谢谢,凯恩

最佳答案

不幸的是,如果没有一些中间编码,这在 JavaScript 中是不可能的。为了理解原因,我们假设您对数据进行了 Base64 解码并发布,就像您在示例中所描述的那样。有效 PHP 文件的前几行(十六进制)可能如下所示:

0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
0000010: 0000 0080 0000 0080 0806 0000 00c3 3e61 ..............>a

如果您查看上传的 PNG 文件的相同范围的十六进制,它将如下所示:

0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
0000010: 0000 00c2 8000 0000 c280 0806 0000 00c3 ................

差异是微妙的。比较第二行的第二列和第三列。在有效文件中,这四个字节是0x00 0x80 0x00 0x00。在您上传的文件中,同样的四个字节是 0x00 0xc2 0x80 0x00。为什么?

JavaScript 字符串是 UTF。这意味着任何 ASCII 二进制值 (0-127) 都用一个字节进行编码。但是,从 128 到 2047 的任何数字都会获得两个字节。上传文件中额外的 0xc2 是这种多字节编码的产物。如果你想确切地知道为什么会发生这种情况,你可以阅读更多关于UTF encoding on Wikipedia的内容。 .

您无法阻止 JavaScript 字符串发生这种情况,因此您无法在不使用 base64 的情况下通过 AJAX 上传此二进制数据。

编辑:经过进一步挖掘,这在某些现代浏览器中是可能的。如果浏览器支持 XMLHttpRequest.prototype.sendAsBinary(Firefox 3 和 4),您可以使用它来发送图像,如下所示:

function postCanvasToURL(url, name, fn, canvas, type) {
var data = canvas.toDataURL(type);
data = data.replace('data:' + type + ';base64,', '');

var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
var boundary = 'ohaiimaboundary';
xhr.setRequestHeader(
'Content-Type', 'multipart/form-data; boundary=' + boundary);
xhr.sendAsBinary([
'--' + boundary,
'Content-Disposition: form-data; name="' + name + '"; filename="' + fn + '"',
'Content-Type: ' + type,
'',
atob(data),
'--' + boundary + '--'
].join('\r\n'));
}

对于没有 sendAsBinary 但有 Uint8Array(Chrome 和 WebKit)的浏览器,您可以像这样填充它:

if (XMLHttpRequest.prototype.sendAsBinary === undefined) {
XMLHttpRequest.prototype.sendAsBinary = function(string) {
var bytes = Array.prototype.map.call(string, function(c) {
return c.charCodeAt(0) & 0xff;
});
this.send(new Uint8Array(bytes).buffer);
};
}

关于php - 使用 Ajax 和 PHP $_FILES 从 Canvas 元素发送图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7628055/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com