我一直在撞墙撞墙,完全被难倒了.我正在尝试使用FineUploader将文件直接上传到我的Amazon S3存储桶.我基本上已经从fineuploader.com网页(直接上传文件到Amazon S3)和服务器端
PHP复制了代码.
当我尝试上传文件时,我看到签名端点的帖子似乎成功运行但是当它尝试上传到S3时,我得到405“方法不允许”错误.
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
- /**
- * 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集团安全政策
- {
- "Version":"2012-10-17","Statement":[{
- "Effect":"Allow","Action":"s3:PutObject","Resource":"arn:aws:s3:::upload.roughdrag.com/*"
- }]
- }
uploader.js是从http://fineuploader.com/source/all.fineuploader-3.9.1.min.js捕获的
控制台响应
- [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
该软件看起来很神奇,但我无法超越这个.任何帮助表示赞赏.
我猜这是将您的自定义域名映射到S3存储桶时创建的DNS问题.解析upload.roughdrag.com后,看起来您已将此CNAME映射到“upload.roughdrag.com.s3-website-us-east-1.amazonaws.com”.尝试将CNAME映射到“upload.roughdrag.com.s3.amazaonaws.com”.
更新1:
如果您在此更改后仍然看到问题,我会在AWS S3 forums中发布.希望员工会回答.您的存储桶/ CNAME可能存在我无法看到的问题.它看起来像是upload.roughdrag.com.s3.amazonaws.com的POST请求,但是向upload.roughdrag.com发送POST请求时出现问题.我用Postman验证了这个.
更新2:
通过最新的CNAME更改,看起来S3正在接受POST请求.