无法将大型HTML5画布POST到服务器?

10
我有一个可以绘制的画布。我需要将其内容保存到服务器,以便以后可以恢复它。
为此,我使用xMLHttpReq.open("POST", url, false);,通过xMLHttpReq.send(*)encodeURIComponent(canvasP.toDataURL())*将数据发送到服务器。
在我的php脚本中,我接收$_POST并使用base64_decode(json_decode($_POST[data]))将其保存到服务器上的.png文件中。
现在,如果画布上只有一些小涂鸦,这个方法完全可行。但是,如果1600x1200像素的画布上有很多东西被绘制了,并且它的大小达到了600kB,那么我的脚本就会失败,而我的服务器上只有一个0kB的png文件。
我该如何解决这个问题?我怎样才能将大型画布发送到服务器?
问题是_POST大小的限制吗?因为无论画布有多大,我都可以通过window.open(canvasP.toDataURL(), "blabla");下载它。
对我来说,这是一个棘手的问题。任何帮助都将不胜感激!
[编辑] 对于超过50多kB的任何内容,PHP仅接收空的$_POST[data]... 所以问题必须出现在canvasP.toDataURL()和POST之间...
[编辑2] 浏览器说“上传中...(xx%)”,直到“完成”。数据去哪了? :C
[编辑3] 这是应用程序,请自行尝试(使用Google Chrome):http://students.info.uaic.ro/~tudor.berechet/ [编辑4] Mike的答案似乎正确关于suhosin。

2
在 PHP 端它失败了什么信息?听起来像是脚本中的内存问题... - Pekka
3
你们服务器的 post_max_size 是多少?发送到服务器的 URI 编码数据的实际大小是多少? - sdleihssirhc
2
您可能无法修改首选项,但您始终可以从php中读取它们:ini_get('post_max_size') - kirilloid
@kirilloid 我应该想到这个。我试过了,它显示“12M”。所以我猜这不是问题的原因... - Spectraljump
1
你需要尝试并从PHP脚本中获取反应。肯定会有一个响应体。我打赌它包含PHP错误。 - Pekka
显示剩余3条评论
1个回答

10
这似乎非常像您的php是使用Suhosin编译的。具有Suhosin的任何post变量的默认长度限制为65000字节,这非常接近您估计的限制。
实际上,您的服务器正在发送带有值PHP/5.2.6-1+lenny9X-Powered-By头。我搜索了这个软件包版本,在Debian网站上他们提到它是使用Suhosin构建的
由于您无法控制服务器配置,解决方案是将画布数据拆分为多个变量,使其低于服务器的post长度限制,然后在PHP中重新组合。如果您检查phpinfo(),它应该显示所有这些限制。 编辑 - 添加示例代码 Javascript:
var canvasData = canvasP.toDataURL(); 
var length = canvasData.length;
var content = '';
var index = 0;
var limit = 64999;
var l;
while (length > 0) {
    if (length <= limit)
        l = length;
    else
        l = limit;

    content += '&content[]=' + canvasData.substr(index * limit, l);
    length -= l;
    index++;
}

xhr.send(content);

我认为你不需要使用encodeURIComponent(),因为toDataURL()会将内容编码为基于URL的安全的base64格式。 PHP:
if (!empty($_POST['content']) && is_array($_POST['content']))
{
    $content = '';
    foreach ($_POST['content'] as $part)
    {
        $content .= $part;
    }
    $content = base64_decode($content);
}

这不是最有效的方法,但可能会对您有所帮助。

在使用Suhosin时仍然会有限制,但通过这种方式,您将能够发送更多的数据。看起来您将被限制为一个数组中的64个部分,每个部分最多65000个字节,然后您还必须使用多个数组。但是,在那一点上,它已经变得太大,以至于大多数人经常上传它可能会更好地将更改以某种方式发送到图像中,而不是整个图像。


感谢先生找出问题所在。我自己对服务器端的东西并不是很有经验。现在,我必须将字符串分成小于65kB的片段,并进行多个POST操作。似乎很麻烦,要在php端将它们全部拼接起来。我需要为每个Post添加“headers”,以便脚本知道如何处理这些内容。难道没有其他方法可以在服务器上保存你的东西吗?例如某种形式的反向流? - Spectraljump
有趣的是...从未想过,可能会有 PHP 构建的限制。 - kirilloid
我不确定除了POST之外是否有更简单的方法来发送数据,但您不一定需要执行多个POST。您只需使用单个POST发送多个变量,每个变量都在65000字节以下。只要所有值的总和低于您的“post_max_size”限制,您就应该没问题。我已更新我的答案,提供了一个可能可用的方法来实现此操作,但未经测试,因此我不确定它是否有效。当然,如果您可以获得没有安装Suhosin的托管,那将会更好,但这并非总是可能的。 - Mike
现在我明白了!我曾经认为suhosin会覆盖12M的post_max_size限制。非常感谢您提供的示例代码。现在我一定能让它正常工作了。我之前使用encodeURIComponent()是因为除了画布内容外,我还要将一个包含URL的不同变量附加到发送的数据中... - Spectraljump
@Myself 【编辑】只是让大家知道,encodeURIComponent(your_base64) 似乎是必须的。没有 URI 编码,它不起作用。换句话说,base64 似乎不是 _POST 安全的。 - Spectraljump

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接