Php 精细上载程序无效响应

Php 精细上载程序无效响应,php,cors,fine-uploader,Php,Cors,Fine Uploader,当前页面: 尝试上载简单jpg文件时,我收到错误: “无效的策略文档或请求标题!” 这是我尝试上传后的index.html、s3handler.php、CORS策略和控制台输出 已完成所有建议的更改 HTML: 小提琴手输出: POST http://typhooncloud.com/fineuploader/s3handler.php HTTP/1.1 Host: typhooncloud.com Connection: keep-alive C

当前页面:

尝试上载简单jpg文件时,我收到错误:

“无效的策略文档或请求标题!”

这是我尝试上传后的index.html、s3handler.php、CORS策略和控制台输出

已完成所有建议的更改

HTML:

小提琴手输出:

      POST http://typhooncloud.com/fineuploader/s3handler.php HTTP/1.1
      Host: typhooncloud.com
      Connection: keep-alive
      Content-Length: 287
      Origin: http://typhooncloud.com
      User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36
      Content-Type: application/json; charset=UTF-8
      Accept: */*
      Referer: http://typhooncloud.com/fineuploader/
      Accept-Encoding: gzip,deflate,sdch
      Accept-Language: en-US,en;q=0.8
      Cookie: __utma=33700260.900109978.1379619256.1379708113.1380038992.6; __utmb=33700260.1.10.1380038992; __utmc=33700260; __utmz=33700260.1380038992.6.2.utmcsr=stackoverflow.com|utmccn=(referral)|utmcmd=referral|utmcct=/questions/18971119/fine-uploader-invalid-response
      AlexaToolbar-ALX_NS_PH: AlexaToolbar/alxg-3.2

      {"expiration":"2013-09-24T16:26:35.948Z","conditions":[{"acl":"private"},{"bucket":"getalink1001"},{"Content-Type":"image/gif"},{"success_action_status":"200"},{"key":"f7e280c4-8cae-4bd7-82c4-d19e71186def.gif"},{"x-amz-meta-qqfilename":"319.gif"},["content-length-range","0","5000000"]]}


      HTTP/1.1 200 OK
      Date: Tue, 24 Sep 2013 16:21:49 GMT
      Server: Apache
      Access-Control-Allow-Origin: http://typhoonupload.com
      Keep-Alive: timeout=5, max=100
      Connection: Keep-Alive
      Transfer-Encoding: chunked
      Content-Type: application/json

      10
      {"invalid":true}
      0

在复制和粘贴PHP示例服务器代码时,似乎忽略了调整某些值。在这种情况下,
handlePreflightedRequest
方法未被修改以反映您的域

应改为:

函数handleReflightedRequest(){
//如果您依赖CORS,则需要在此处调整允许的域。
标题('Access-Control-Allow-Origin:http://typhooncloud.com');
}

另外,
handleReflightedRequest
方法可能应该重命名为
handleCorsRequest
,以避免混淆。我刚刚在服务器repo中完成了这项工作。不过,您实际上不需要这样做,因为这不会影响代码的行为。

看起来,在复制和粘贴PHP示例服务器代码时,您忽略了调整一些值。在这种情况下,
handlePreflightedRequest
方法未被修改以反映您的域

应改为:

函数handleReflightedRequest(){
//如果您依赖CORS,则需要在此处调整允许的域。
标题('Access-Control-Allow-Origin:http://typhooncloud.com');
}


另外,
handleReflightedRequest
方法可能应该重命名为
handleCorsRequest
,以避免混淆。我刚刚在服务器repo中完成了这项工作。不过,您实际上不需要这样做,因为这不会影响代码的行为。

旁注。让我指出一个关键的区别。在javascript代码中编写
sizeLimit:5000000
,但在PHP中编写
$expectedMaxSize=15000000
。这些值必须完全匹配。

旁注。让我指出一个关键的区别。在javascript代码中编写
sizeLimit:5000000
,但在PHP中编写
$expectedMaxSize=15000000
。这些值必须完全匹配。

您必须提供更多信息。看起来您只是简单地复制并粘贴了一个提供的服务器端示例。您是否在跨来源的环境中工作?让我们从启用调试选项的浏览器开发人员控制台的内容开始。我已经在“控制台输出”中包含了这些内容,如果您愿意,您当然可以自己现场试用,提前谢谢。请编辑您的问题,将“调试”选项设置为“True”时包含控制台输出。您将需要提供更多信息。看起来您只是简单地复制并粘贴了一个提供的服务器端示例。您是否在跨来源的环境中工作?让我们从启用了调试选项的浏览器开发人员控制台的内容开始。我已经在“控制台输出”中包含了这些内容,如果您愿意,您当然可以自己现场尝试,提前谢谢您。编辑您的问题以包括控制台输出,并将调试选项设置为TrueModed,如上所示进行了更改,结果仍然相同。您还错误地修改了
handlePreflight
方法。删除
访问控制允许方法:PUT
访问控制允许方法:DELETE
行。不仅每个响应多次写入此标题是不正确的,而且Fine Uploader将只向您的签名服务器发送POST请求,假设您遵循fineuploader.com上的示例代码(似乎是这样)。好的,我只是添加了这些额外的标题以使其正常工作,因为没有他们就不是。。。请查看新的响应控制台输出,以及新文件本身。。。感谢您的帮助您不能在响应中使用通配符作为访问控制允许标头的值。规范不允许这样做。我强烈建议你花些时间阅读Fine Uploader S3文档和博客文章(以及Fine Uploader和相关博客文章的CORS文档),如果你想偏离示例,而不是在黑暗中继续尝试这些内容。该示例包含预期内容类型标题的条目。您将其注释掉,然后将其删除。即使允许使用通配符,在大多数情况下也不应使用通配符……因为您在跨源环境中工作,您需要至少对同源策略和CORS规范有一个基本的了解。我已经在Fine Uploader博客上写了关于这一点的博客,并链接到一篇描述CORS要求的必读文章。然而,服务器端PHP示例确实为您完成了所有这些。您所需要做的就是调整一些值。如果您需要进行更剧烈的更改(而且您的情况似乎不足以证明这一点),您需要先花一些时间熟悉相关概念。如上所述进行了更改,结果仍然相同。您还错误地修改了
handlePreflight
方法。删除
访问控制允许方法:PUT
访问控制允许方法:DELETE
行。不仅每个响应多次写入此标题是不正确的,而且Fine Uploader将只向您的签名服务器发送POST请求,假设您遵循fineuploader.com上的示例代码(似乎是这样)。好的,我只是添加了这些额外的标题以使其正常工作,因为没有他们就不是。。。请查看新的响应控制台输出,以及新文件本身。。。感谢您的帮助您不能在响应中使用通配符作为访问控制允许标头的值。规范不允许这样做。我强烈建议你花点时间阅读这本精美的Uplo
    <?php
    /**
     * PHP Server-Side Example for Fine Uploader S3.
     * Maintained by Widen Enterprises.
     *
     * Note: This is the exact server-side code used by the S3 example
     * on fineuploader.com.
     *
     * This example:
     *  - handles both CORS and non-CORS environments
     *  - handles delete file requests for both DELETE and POST methods
     *  - Performs basic inspections on the policy documents and REST headers before signing them
     *  - Ensures again the file size does not exceed the max (after file is in S3)
     *  - signs policy documents (simple uploads) and REST requests
     *    (chunked/multipart uploads)
     *
     * Requirements:
     *  - PHP 5.3 or newer
     *  - Amazon PHP SDK (only if utilizing the AWS SDK for deleting files or otherwise examining them)
     *
     * If you need to install the AWS SDK, see http://docs.aws.amazon.com/aws-sdk-php-2/guide/latest/installation.html.
     */

    // You can remove these two lines if you are not using Fine Uploader's
    // delete file feature
    require("aws/aws-autoloader.php");

    use Aws\S3\S3Client;


    // These assume you have the associated AWS keys stored in
    // the associated system environment variables
    $clientPrivateKey = $_SERVER['MYSECRETKEY'];
    // These two keys are only needed if the delete file feature is enabled
    // or if you are, for example, confirming the file size in a successEndpoint
    // handler via S3's SDK, as we are doing in this example.
    $serverPublicKey = $_SERVER['MYPRIVATEKEY'];
    $serverPrivateKey = $_SERVER['MYSECRETKEY'];

    // The following variables are used when validating the policy document
    // sent by the uploader: 
    $expectedBucketName = "getalink1001";
    // $expectedMaxSize is the value you set the sizeLimit property of the 
    // validation option. We assume it is `null` here. If you are performing
    // validation, then change this to match the integer value you specified
    // otherwise your policy document will be invalid.
    // http://docs.fineuploader.com/branch/develop/api/options.html#validation-option
    $expectedMaxSize = 15000000;

    $method = getRequestMethod();

    // This first conditional will only ever evaluate to true in a
    // CORS environment
    if ($method == 'OPTIONS') {
        handlePreflight();
    }
    // This second conditional will only ever evaluate to true if
    // the delete file feature is enabled
    else if ($method == "DELETE") {
        handleCorsRequest(); // only needed in a CORS environment
        deleteObject();
    }
    // This is all you really need if not using the delete file feature
    // and not working in a CORS environment
    else if ($method == 'POST') {
        handleCorsRequest();

        // Assumes the successEndpoint has a parameter of "success" associated with it,
        // to allow the server to differentiate between a successEndpoint request
        // and other POST requests (all requests are sent to the same endpoint in this example).
        // This condition is not needed if you don't require a callback on upload success.
        if (isset($_REQUEST["success"])) {
            verifyFileInS3();
        }
        else {
            signRequest();
        }
    }

    // This will retrieve the "intended" request method.  Normally, this is the
    // actual method of the request.  Sometimes, though, the intended request method
    // must be hidden in the parameters of the request.  For example, when attempting to
    // send a DELETE request in a cross-origin environment in IE9 or older, it is not
    // possible to send a DELETE request.  So, we send a POST with the intended method,
    // DELETE, in a "_method" parameter.
    function getRequestMethod() {
        global $HTTP_RAW_POST_DATA;

        // This should only evaluate to true if the Content-Type is undefined
        // or unrecognized, such as when XDomainRequest has been used to
        // send the request.
        if(isset($HTTP_RAW_POST_DATA)) {
          parse_str($HTTP_RAW_POST_DATA, $_POST);
        }

        if ($_POST['_method'] != null) {
            return $_POST['_method'];
        }

        return $_SERVER['REQUEST_METHOD'];
    }

    // Only needed in cross-origin setups
    function handleCorsRequest() {
        // If you are relying on CORS, you will need to adjust the allowed domain here.
        header('Access-Control-Allow-Origin: http://typhoonupload.com');
    }

    // Only needed in cross-origin setups
    function handlePreflight() {
        handleCorsRequest();
        header('Access-Control-Allow-Methods: POST');
        header('Access-Control-Allow-Headers: Content-Type');
    }

    function getS3Client() {
        global $serverPublicKey, $serverPrivateKey;

        return S3Client::factory(array(
            'key' => $serverPublicKey,
            'secret' => $serverPrivateKey
        ));
    }

    // Only needed if the delete file feature is enabled
    function deleteObject() {
        getS3Client()->deleteObject(array(
            'Bucket' => $_POST['bucket'],
            'Key' => $_POST['key']
        ));
    }

    function signRequest() {
        header('Content-Type: application/json');

        $responseBody = file_get_contents('php://input');
        $contentAsObject = json_decode($responseBody, true);
        $jsonContent = json_encode($contentAsObject);

        $headersStr = $contentAsObject["headers"];
        if ($headersStr) {
            signRestRequest($headersStr);
        }
        else {
            signPolicy($jsonContent);
        }
    }

    function signRestRequest($headersStr) {
        if (isValidRestRequest($headersStr)) {
            $response = array('signature' => sign($headersStr));
            echo json_encode($response);
        }
        else {
            echo json_encode(array("invalid" => true));
        }
    }

    function isValidRestRequest($headersStr) {
        global $expectedBucketName;

        $pattern = "/\/$expectedBucketName\/.+$/";
        preg_match($pattern, $headersStr, $matches);

        return count($matches) > 0;
    }

    function signPolicy($policyStr) {
        $policyObj = json_decode($policyStr, true);

        if (isPolicyValid($policyObj)) {
            $encodedPolicy = base64_encode($policyStr);
            $response = array('policy' => $encodedPolicy, 'signature' => sign($encodedPolicy));
            echo json_encode($response);
        }
        else {
            echo json_encode(array("invalid" => true));
        }
    }

    function isPolicyValid($policy) {
        global $expectedMaxSize, $expectedBucketName;

        $conditions = $policy["conditions"];
        $bucket = null;
        $parsedMaxSize = null;

        for ($i = 0; $i < count($conditions); ++$i) {
            $condition = $conditions[$i];

            if (isset($condition["bucket"])) {
                $bucket = $condition["bucket"];
            }
            else if (isset($condition[0]) && $condition[0] == "content-length-range") {
                $parsedMaxSize = $condition[2];
            }
        }

        return $bucket == $expectedBucketName && $parsedMaxSize == (string)$expectedMaxSize;
    }

    function sign($stringToSign) {
        global $clientPrivateKey;

        return base64_encode(hash_hmac(
                'sha1',
                $stringToSign,
                $clientPrivateKey,
                true
            ));
    }

    // This is not needed if you don't require a callback on upload success.
    function verifyFileInS3() {
        global $expectedMaxSize;

        $bucket = $_POST["bucket"];
        $key = $_POST["key"];

        // If utilizing CORS, we return a 200 response with the error message in the body
        // to ensure Fine Uploader can parse the error message in IE9 and IE8,
        // since XDomainRequest is used on those browsers for CORS requests.  XDomainRequest
        // does not allow access to the response body for non-success responses.
        if (getObjectSize($bucket, $key) > $expectedMaxSize) {
            // You can safely uncomment this next line if you are not depending on CORS
            //header("HTTP/1.0 500 Internal Server Error");
            deleteObject();
            echo json_encode(array("error" => "File is too big!"));
        }
        else {
            echo json_encode(array("tempLink" => getTempLink($bucket, $key)));
        }
    }

    // Provide a time-bombed public link to the file.
    function getTempLink($bucket, $key) {
        $client = getS3Client();
        $url = "{$bucket}/{$key}";
        $request = $client->get($url);

        return $client->createPresignedUrl($request, '+15 minutes');
    }

    function getObjectSize($bucket, $key) {
        $objInfo = getS3Client()->headObject(array(
                'Bucket' => $bucket,
                'Key' => $key
            ));
        return $objInfo['ContentLength'];
    }
    ?>
    <?xml version="1.0" encoding="UTF-8"?>
    <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
        <CORSRule>
            <AllowedOrigin>*</AllowedOrigin>
            <AllowedMethod>POST</AllowedMethod>
            <AllowedMethod>PUT</AllowedMethod>
            <AllowedMethod>DELETE</AllowedMethod>
            <MaxAgeSeconds>3000</MaxAgeSeconds>
            <ExposeHeader>ETag</ExposeHeader>
            <AllowedHeader>*</AllowedHeader>
        </CORSRule>
    </CORSConfiguration>
      [FineUploader 3.9.0-3] Received 1 files or inputs. s3.jquery.fineuploader-3.9.0-3.js:164
      [FineUploader 3.9.0-3] Submitting S3 signature request for 0 s3.jquery.fineuploader-3.9.0-3.js:164
      [FineUploader 3.9.0-3] Sending POST request for 0 s3.jquery.fineuploader-3.9.0-3.js:164
      [FineUploader 3.9.0-3] Invalid policy document or request headers! s3.jquery.fineuploader-3.9.0-3.js:169
      [FineUploader 3.9.0-3] Policy signing failed.  Invalid policy document or request headers! s3.jquery.fineuploader-3.9.0-3.js:169
      [FineUploader 3.9.0-3] Received response status 0 with body:  s3.jquery.fineuploader-3.9.0-3.js:164
      [FineUploader 3.9.0-3] Upload attempt for file ID 0 to S3 is complete s3.jquery.fineuploader-3.9.0-3.js:164
      POST http://typhooncloud.com/fineuploader/s3handler.php HTTP/1.1
      Host: typhooncloud.com
      Connection: keep-alive
      Content-Length: 287
      Origin: http://typhooncloud.com
      User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36
      Content-Type: application/json; charset=UTF-8
      Accept: */*
      Referer: http://typhooncloud.com/fineuploader/
      Accept-Encoding: gzip,deflate,sdch
      Accept-Language: en-US,en;q=0.8
      Cookie: __utma=33700260.900109978.1379619256.1379708113.1380038992.6; __utmb=33700260.1.10.1380038992; __utmc=33700260; __utmz=33700260.1380038992.6.2.utmcsr=stackoverflow.com|utmccn=(referral)|utmcmd=referral|utmcct=/questions/18971119/fine-uploader-invalid-response
      AlexaToolbar-ALX_NS_PH: AlexaToolbar/alxg-3.2

      {"expiration":"2013-09-24T16:26:35.948Z","conditions":[{"acl":"private"},{"bucket":"getalink1001"},{"Content-Type":"image/gif"},{"success_action_status":"200"},{"key":"f7e280c4-8cae-4bd7-82c4-d19e71186def.gif"},{"x-amz-meta-qqfilename":"319.gif"},["content-length-range","0","5000000"]]}


      HTTP/1.1 200 OK
      Date: Tue, 24 Sep 2013 16:21:49 GMT
      Server: Apache
      Access-Control-Allow-Origin: http://typhoonupload.com
      Keep-Alive: timeout=5, max=100
      Connection: Keep-Alive
      Transfer-Encoding: chunked
      Content-Type: application/json

      10
      {"invalid":true}
      0