使用 S3 在 fineUploader 中获取 404

Getting 404 in fineUploader using S3

我正在关注将 fineuploader 与 Amazon S3 集成的博客 example
但是我收到 404 错误

[Fine Uploader 5.2.2] Detected valid file button click event on file 'Captura de pantalla 2015-07-28 a las 10.23.41 PM.png', ID: 0.
s3.jquery.fine-uploader.js:244 [Fine Uploader 5.2.2] Retrying upload for 'Captura de pantalla 2015-07-28 a las 10.23.41 PM.png' (id: 0)...
s3.jquery.fine-uploader.js:244 [Fine Uploader 5.2.2] Sending simple upload request for 0
s3.jquery.fine-uploader.js:244 [Fine Uploader 5.2.2] Submitting S3 signature request for 0
s3.jquery.fine-uploader.js:244 [Fine Uploader 5.2.2] Sending POST request for 0
s3.jquery.fine-uploader.js:244 [Fine Uploader 5.2.2] Sending upload request for 0
s3.jquery.fine-uploader.js:9744 OPTIONS http://submission-temp.s3-website-us-east-1.amazonaws.com/ (anonymous function) @ s3.jquery.fine-uploader.js:9744(anonymous function) @ s3.jquery.fine-uploader.js:1119qq.each @ s3.jquery.fine-uploader.js:658qq.extend.success @ s3.jquery.fine-uploader.js:1118simple.setup.simple.initParams.then.promise.failure.error @ s3.jquery.fine-uploader.js:9779(anonymous function) @ s3.jquery.fine-uploader.js:1119qq.each @ s3.jquery.fine-uploader.js:658qq.extend.success @ s3.jquery.fine-uploader.js:1118signPolicyCallback.then.errorMessage @ s3.jquery.fine-uploader.js:7863(anonymous function) @ s3.jquery.fine-uploader.js:1119qq.each @ s3.jquery.fine-uploader.js:658qq.extend.success @ s3.jquery.fine-uploader.js:1118handleSignatureReceived @ s3.jquery.fine-uploader.js:8626onComplete @ s3.jquery.fine-uploader.js:3807(anonymous function) @ s3.jquery.fine-uploader.js:3912
gallery.html:1 XMLHttpRequest cannot load http://submission-temp.s3-website-us-east-1.amazonaws.com/. Invalid HTTP status code 404
s3.jquery.fine-uploader.js:244 [Fine Uploader 5.2.2] Received response status 0 with body: 
s3.jquery.fine-uploader.js:244 [Fine Uploader 5.2.2] Simple upload request failed for 0

这是我在存储桶中的 CORS 配置

<?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>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <ExposeHeader>ETag</ExposeHeader>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

这是我的客户端代码

$('#qq-template2').fineUploaderS3({
    template: 'qq-template',
    debug: true,
    request: {
      endpoint: "http://submission-temp.s3-website-us-east-1.amazonaws.com",
      accessKey: "AKXXAJXDJXXQ6XJPTUA"
    },
    signature: {
      endpoint: "./server/signature/endpoint.php"
    },
    uploadSuccess: {
      endpoint: "./success.html"
    },
    iframeSupport: {
      localBlankPagePath: "./success.html"
    },
      cors: {
     expected: true
     }

  });

这是我的服务器代码

require __DIR__.'/../../../vendor/autoload.php';

use Aws\S3\S3Client;
// These assume you have the associated AWS keys stored in
// the associated system environment variables
$clientPrivateKey = "XXXXXXXXXXX";
// 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 = "XXXXXXXXX";
$serverPrivateKey = "XXXXXXX+XXXXXX";

// The following variables are used when validating the policy document
// sent by the uploader: 
$expectedBucketName = "submission-temp";
// $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 = null;
$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(shouldIncludeThumbnail());
    }
    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 (isset($_POST['_method'])) {
        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: *');
}
// 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);
    if (!empty($contentAsObject["headers"])) {
        signRestRequest($contentAsObject["headers"]);
    }
    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($includeThumbnail) {
    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 (isset($expectedMaxSize) && 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!", "preventRetry" => true));
    }
    else {
        $link = getTempLink($bucket, $key);
        $response = array("tempLink" => $link);
        if ($includeThumbnail) {
            $response["thumbnailUrl"] = $link;
        }
        echo json_encode($response);
    }
}
// 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'];
}
// Return true if it's likely that the associate file is natively
// viewable in a browser.  For simplicity, just uses the file extension
// to make this determination, along with an array of extensions that one
// would expect all supported browsers are able to render natively.
function isFileViewableImage($filename) {
    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
    $viewableExtensions = array("jpeg", "jpg", "gif", "png");
    return in_array($ext, $viewableExtensions);
}
// Returns true if we should attempt to include a link
// to a thumbnail in the uploadSuccess response.  In it's simplest form
// (which is our goal here - keep it simple) we only include a link to
// a viewable image and only if the browser is not capable of generating a client-side preview.
function shouldIncludeThumbnail() {
    $filename = $_POST["name"];
    $isPreviewCapable = $_POST["isBrowserPreviewCapable"] == "true";
    $isFileViewableImage = isFileViewableImage($filename);
    return !$isPreviewCapable && $isFileViewableImage;
}

有人可以帮助理解为什么我会收到此回复,或者我该如何解决??谢谢

日志非常清楚 - 您的 S3 端点正在响应 404,这意味着它根本不存在或者您的存储桶可能存在问题。