6

Tôi đã đập đầu vào tường và điều này hoàn toàn bị vấp. Tôi đang cố gắng sử dụng FineUploader để tải tệp trực tiếp lên thùng Amazon S3 của tôi. Về cơ bản tôi đã sao chép mã từ trang web fineuploader.com (Tải tệp trực tiếp lên Amazon S3) và PHP phía máy chủ.Trình tải lên tốt lên thùng S3 nhận 405 Lỗi không được phép theo phương pháp

Khi tôi cố gắng tải tệp lên, tôi thấy bài đăng đến điểm cuối chữ ký dường như hoạt động thành công nhưng khi cố gắng tải lên S3, tôi nhận được lỗi "Không được phép".

HTML

<!DOCTYPE html> 
<html > 
<head > 
    <meta charset = "utf-8" > 
    <link href = "http://fineuploader.com/source/fineuploader-3.9.1.min.css" rel = "stylesheet" > 
</head > 
<body > 
<div id = "fine-uploader" ></div > 

<script src = "http://code.jquery.com/jquery-latest.js" ></script > 
<script src = "js/uploader.js" ></script > 
<script > 
    $(document).ready(function() { 
     $("#fine-uploader").fineUploaderS3({ 
      debug: true, 
      request: { 
       endpoint: 'upload.roughdrag.com', 
       accessKey: 'AKIAJL37USSCV......' 
      }, 

      signature: { 
       endpoint: 'handlers/uploadHandler.php' 
      }, 
      uploadSuccess: { 
       endpoint: 'index.php' 
      }, 
      iframeSupport: { 
       localBlankPagePath: 'blank.html' 
      }, 
      retry: { 
       enableAuto: true // defaults to false 
      }, 

      paste: { 
       targetElement: $(document), 
       promptForName: true 
      }, 

      deleteFile: { 
       enabled: true, 
       endpoint: 'handlers/uploadHandler.php' 
      } 
     }); 
    }); 
</script > 
</body > 
</html > 

PHP Chữ ký Endpoint - uploadHandler.php Cấu hình

<?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('../../includes/functions.php'); 
use Aws\S3\S3Client; 

// These assume you have the associated AWS keys stored in 
// the associated system environment variables 
$clientPrivateKey = '{removed}'; 
// 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 = '{removed}'; 
$serverPrivateKey = '{removed}'; 

// The following variables are used when validating the policy document 
// sent by the uploader: 
$expectedBucketName = "upload.roughdrag.com"; 
// $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 = 5000000; 

$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://www.roughdrag.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" => "Your 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']; 
} 

?> 

Amazon S3 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> 
     <MaxAgeSeconds>3000</MaxAgeSeconds> 
     <ExposeHeader>ETag</ExposeHeader> 
     <AllowedHeader>*</AllowedHeader> 
    </CORSRule> 
</CORSConfiguration> 

IAM Security Group Policy

{ 
    "Version":"2012-10-17", 
    "Statement":[{ 
    "Effect":"Allow", 
    "Action":"s3:PutObject", 
    "Resource":"arn:aws:s3:::upload.roughdrag.com/*" 
    }] 
} 

uploader.js bị bắt từ http://fineuploader.com/source/all.fineuploader-3.9.1.min.js

điều khiển phản ứng

[FineUploader 3.9.0-3] Grabbed 1 dropped files. 

[FineUploader 3.9.0-3] Received 1 files or inputs. 

[FineUploader 3.9.0-3] Submitting S3 signature request for 0 

[FineUploader 3.9.0-3] Sending POST request for 0 

POST http://www.roughdrag.com/handlers/uploadHandler.php 200 OK 195ms 

[FineUploader 3.9.0-3] Sending upload request for 0 

POST http://upload.roughdrag.com/ 405 Method Not Allowed 559ms 

"NetworkError: 405 Method Not Allowed - http://upload.roughdrag.com/" 

[FineUploader 3.9.0-3] Received response status 405 with body: <html> 
<head><title>405 Method Not Allowed</title></head> 
<body> 
<h1>405 Method Not Allowed</h1> 
<ul> 
<li>Code: MethodNotAllowed</li> 
<li>Message: The specified method is not allowed against this resource.</li> 
<li>ResourceType: OBJECT</li> 
<li>Method: POST</li> 
<li>RequestId: 3493FE605B461EAF</li> 
<li>HostId: HDXmtSpHufy6LDIH1Nsp0oYkLDvTC3XKFRRIadw66gmaMsF53Z3WYsCWooOoRcw2</li> 
</ul> 
<hr/> 
</body> 
</html> 

[FineUploader 3.9.0-3] Waiting 5 seconds before retrying breakout.jpg... 

[FineUploader 3.9.0-3] Detected valid cancel, retry, or delete click event on file 'breakout.jpg', ID: 0. 

[FineUploader 3.9.0-3] Cancelling 0 

Phần mềm này trông tuyệt vời nhưng tôi chỉ không thể vượt qua điều này. Bất kỳ trợ giúp được đánh giá cao.

Trả lời

4

Tôi đoán đây là sự cố DNS được tạo khi bạn ánh xạ tên miền tùy chỉnh của mình vào nhóm S3 của mình. Sau khi giải quyết upload.roughdrag.com, có vẻ như bạn đã ánh xạ CNAME này thành "upload.roughdrag.com.s3-website-us-east-1.amazonaws.com". Hãy thử ánh xạ CNAME đó để "upload.roughdrag.com.s3.amazaonaws.com" thay thế.

Cập nhật 1:

Nếu bạn vẫn đang nhìn thấy các vấn đề sau sự thay đổi này, tôi sẽ đăng bài trong AWS S3 forums. Hy vọng rằng một nhân viên sẽ trả lời. Có thể có vấn đề với nhóm/CNAME của bạn mà tôi không thể thấy từ phía tôi. Dường như một yêu cầu POST để upload.roughdrag.com.s3.amazonaws.com vẫn hoạt động, nhưng có vấn đề khi gửi yêu cầu POST để tải lên.roughdrag.com. Tôi đã xác minh điều này với Postman.

Cập nhật 2:

Với sự thay đổi CNAME mới nhất của bạn, có vẻ như các yêu cầu POST đang được chấp nhận bởi S3.

+3

Đó là vấn đề, Ray.Thuộc tính nhóm cho "lưu trữ trang web tĩnh" chỉ định điểm cuối là upload.roughdrag.com.s3-website-us-east-1.amazonaws.com nhưng ngay khi tôi thay đổi nó thành upload.roughdrag.com.s3.amazonaws. com này bắt đầu làm việc cho tôi. Cảm ơn nhiều. – jjj916

+0

Tôi đang có một tình huống rất giống với áp phích gốc. Bạn có thể chia sẻ cài đặt DNS của mình cho tôi không? Và, bạn đang sử dụng Amazon cho DNS? Tôi chỉ đang ánh xạ 'uploads.mydomain.com' vào điểm cuối của nhóm của tôi' BUCKETNAME.s3-website-us-east-1.amazonaws.com'. – Colin

+0

"Sau khi giải quyết upload.roughdrag.com, có vẻ như bạn đã ánh xạ CNAME này thành" upload.roughdrag.com.s3-website-us-east-1.amazonaws.com ". Hãy thử ánh xạ CNAME đó để" upload.roughdrag .com.s3.amazaonaws.com "thay thế" - đã làm việc cho tôi – jaspreet21anand

1

Tôi gặp vấn đề tương tự. Đã sửa lỗi bằng cách thêm khu vực vào chức năng dưới đây:

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

    return S3Client::factory(array(
     'key' => $serverPublicKey, 
     'secret' => $serverPrivateKey, 
     'region' => 'ap-southeast-2' //Revomve from non Sydney bucket 
    )); 
} 

Tìm vùng của nhóm bằng cách nhấp vào thuộc tính. Sau đó, lưu trữ trang web tĩnh và chỉ lấy chi tiết từ điểm cuối từ ap-xxxxx-x

Các vấn đề liên quan