jQuery AJAX 调用在传递 Rgraph 图像数据时返回 403 Forbidden 错误

jQuery AJAX call returning 403 Forbidden error when passing Rgraph image data

我正在做一个项目,我使用 Rgraph PHP 库实现了几个 graphs/charts。在我的脚本中,我对图表执行以下操作:

  1. 计算图形点并使用 Rgraph Draw() 方法绘制图形。
  2. 使用 canvas.toDataURL() 方法创建图像数据变量。
  3. 使用 jQuery AJAX $.post() 方法将此图像数据变量传递到服务器。
  4. 通过 PHP 脚本将图像保存到服务器。

此解决方案中的所有内容在我的本地主机上都运行良好,但是在开发服务器上,传递图像数据的 AJAX 请求 returns a 403 Error.

我记录了客户端和服务器端的数据以确定问题所在。客户端日志记录确认传递的 imageData 变量看起来正确。但是,服务器端日志记录确认正在传递的 imageData 变量是导致问题的原因。

有一个 very similar question posted last year about this,但是他们无法确定其根本原因。谁能帮我指出解决这个问题的正确方向?

我认为这可能是数据编码问题,但如果是这种情况,为什么它在一台服务器上工作而不在另一台服务器上工作?

我的相关Javascript:

radar.Set('chart.contextmenu', [
     ['Get PNG', RGraph.showPNG],
     null,
     ['Cancel', function () {}]
]);

radar.Draw();   

var imageData = radar.canvas.toDataURL("image/png");

console.log('imageData: ' + imageData);
console.log('filename: ' + 'tmpRadar<?php echo $us['UsersSurvey']['user_id']; ?>-<?php echo $survey['Survey']['id']; ?>.png');

$.post("/Surveys/save_chart", { 
    src     : imageData, 
    filename: 'tmpRadar<?php echo $us['UsersSurvey']['user_id']; ?>-<?php echo $survey['Survey']['id']; ?>.png'
});

客户端日志记录:

imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABLAAAAOECAYAAACxbcj6AAAgAElEQ…AgQIAAgVECAqxR49YsAQIECBAgQIAAAQIECBAgQKCfwP8CXHJ+WDHVMbcAAAAASUVORK5CYII=
filename: tmpRadar19-1.png
POST http://website.com/Surveys/save_chart 403 (Forbidden)

PHP 调用的函数 AJAX:

public function save_chart() {
    if($this->request->is('ajax')) {
        $this->log('request data: '.print_r($this->request->data, true));

        $filename = $this->request->data['filename'];

        $src     = $this->request->data['src'];
        $src     = substr($src, strpos($src, ",") + 1);
        $decoded = base64_decode($src);

        $fp = fopen(WWW_ROOT.'files/graphs/'.$filename,'wb');
        if(fwrite($fp, $decoded)) {
            fclose($fp);
            return json_encode(array('success' => '1'));
        } else {
            fclose($fp);
            return json_encode(array('success' => '0'));
        }
    }
}

您对 .post() 中数据的使用有点不对。如果您尝试传递一个 JSON 对象作为 .post() 的第二个参数的数据,您需要将其正确地组成一个 JSON 字符串。尝试用 JSON.stringify() 包裹你的字典。它将获取您的 javascript 值 {key1: value1, key2: value2} 并对其进行格式化。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

$.post("/Surveys/save_chart", JSON.stringify(
  { 
    src     : imageData, 
    filename: 'tmpRadar<?php echo $us['UsersSurvey']['user_id']; ?>-<?php echo $survey['Survey']['id']; ?>.png'
  }
) //end stringify 
)//end post;

它与 mod_security(Apache 模块)和 URL 的 http:// 部分有关。

这里有两个选择,

  • 修改 Apache 模块
  • 客户端解决方法

尝试从您发布的表单中删除 imagedata,它应该会提交。

来源:403-on-form-submit

假设 CORS 不是这里的问题(这听起来不像是因为它在您的本地主机上工作正常并且听起来像您的 POSTing 一样您收到原始 GET 的域),这可能是本地主机上的 Apache 和 devbox 之间的配置错误。鉴于问题仅出在您的 base 64 编码图像 POST,它可能太大,因此 apache 拒绝它。

根据 this SO post,尝试在您的 php.ini 中设置以下内容:

post_max_size=20M
upload_max_filesize=20M

或在 .htaccess/httpd.conf/virtualhost:

php_value post_max_size 20M
php_value upload_max_filesize=20M

请注意,在您 post apache 错误日志之前,我无法确定这是否是原因。