php – 精简上传到S3存储桶获取405方法不允许错误

前端之家收集整理的这篇文章主要介绍了php – 精简上传到S3存储桶获取405方法不允许错误前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在撞墙撞墙,完全被难倒了.我正在尝试使用FineUploader将文件直接上传到我的Amazon S3存储桶.我基本上已经从fineuploader.com网页(直接上传文件到Amazon S3)和服务器端 PHP复制了代码.

当我尝试上传文件时,我看到签名端点的帖子似乎成功运行但是当它尝试上传到S3时,我得到405“方法不允许”错误.

HTML

  1. <!DOCTYPE html>
  2. <html >
  3. <head >
  4. <Meta charset = "utf-8" >
  5. <link href = "http://fineuploader.com/source/fineuploader-3.9.1.min.css" rel = "stylesheet" >
  6. </head >
  7. <body >
  8. <div id = "fine-uploader" ></div >
  9.  
  10. <script src = "http://code.jquery.com/jquery-latest.js" ></script >
  11. <script src = "js/uploader.js" ></script >
  12. <script >
  13. $(document).ready(function () {
  14. $("#fine-uploader").fineUploaderS3({
  15. debug: true,request: {
  16. endpoint: 'upload.roughdrag.com',accessKey: 'AKIAJL37USSCV......'
  17. },signature: {
  18. endpoint: 'handlers/uploadHandler.PHP'
  19. },uploadSuccess: {
  20. endpoint: 'index.PHP'
  21. },iframeSupport: {
  22. localBlankPagePath: 'blank.html'
  23. },retry: {
  24. enableAuto: true // defaults to false
  25. },paste: {
  26. targetElement: $(document),promptForName: true
  27. },deleteFile: {
  28. enabled: true,endpoint: 'handlers/uploadHandler.PHP'
  29. }
  30. });
  31. });
  32. </script >
  33. </body >
  34. </html >

PHP签名端点 – uploadHandler.PHP

  1. <?PHP
  2. /**
  3. * PHP Server-Side Example for Fine Uploader S3.
  4. * Maintained by Widen Enterprises.
  5. *
  6. * Note: This is the exact server-side code used by the S3 example
  7. * on fineuploader.com.
  8. *
  9. * This example:
  10. * - handles both CORS and non-CORS environments
  11. * - handles delete file requests for both DELETE and POST methods
  12. * - Performs basic inspections on the policy documents and REST headers before signing them
  13. * - Ensures again the file size does not exceed the max (after file is in S3)
  14. * - signs policy documents (simple uploads) and REST requests
  15. * (chunked/multipart uploads)
  16. *
  17. * Requirements:
  18. * - PHP 5.3 or newer
  19. * - Amazon PHP SDK (only if utilizing the AWS SDK for deleting files or otherwise examining them)
  20. *
  21. * If you need to install the AWS SDK,see http://docs.aws.amazon.com/aws-sdk-PHP-2/guide/latest/installation.html.
  22. */
  23.  
  24. // You can remove these two lines if you are not using Fine Uploader's
  25. // delete file feature
  26. require('../../includes/functions.PHP');
  27. use Aws\S3\S3Client;
  28.  
  29. // These assume you have the associated AWS keys stored in
  30. // the associated system environment variables
  31. $clientPrivateKey = '{removed}';
  32. // These two keys are only needed if the delete file feature is enabled
  33. // or if you are,for example,confirming the file size in a successEndpoint
  34. // handler via S3's SDK,as we are doing in this example.
  35. $serverPublicKey = '{removed}';
  36. $serverPrivateKey = '{removed}';
  37.  
  38. // The following variables are used when validating the policy document
  39. // sent by the uploader:
  40. $expectedBucketName = "upload.roughdrag.com";
  41. // $expectedMaxSize is the value you set the sizeLimit property of the
  42. // validation option. We assume it is `null` here. If you are performing
  43. // validation,then change this to match the integer value you specified
  44. // otherwise your policy document will be invalid.
  45. // http://docs.fineuploader.com/branch/develop/api/options.html#validation-option
  46. //$expectedMaxSize = 5000000;
  47.  
  48. $method = getRequestMethod();
  49.  
  50. // This first conditional will only ever evaluate to true in a
  51. // CORS environment
  52. if ($method == 'OPTIONS') {
  53. handlePreflight();
  54. } // This second conditional will only ever evaluate to true if
  55. // the delete file feature is enabled
  56. else if ($method == "DELETE") {
  57. handleCorsRequest(); // only needed in a CORS environment
  58. deleteObject();
  59. } // This is all you really need if not using the delete file feature
  60. // and not working in a CORS environment
  61. else if ($method == 'POST') {
  62. handleCorsRequest();
  63.  
  64. // Assumes the successEndpoint has a parameter of "success" associated with it,// to allow the server to differentiate between a successEndpoint request
  65. // and other POST requests (all requests are sent to the same endpoint in this example).
  66. // This condition is not needed if you don't require a callback on upload success.
  67. if (isset($_REQUEST["success"])) {
  68. verifyFileInS3();
  69. } else {
  70. signRequest();
  71. }
  72. }
  73.  
  74. // This will retrieve the "intended" request method. Normally,this is the
  75. // actual method of the request. Sometimes,though,the intended request method
  76. // must be hidden in the parameters of the request. For example,when attempting to
  77. // send a DELETE request in a cross-origin environment in IE9 or older,it is not
  78. // possible to send a DELETE request. So,we send a POST with the intended method,// DELETE,in a "_method" parameter.
  79. function getRequestMethod()
  80. {
  81. global $HTTP_RAW_POST_DATA;
  82.  
  83. // This should only evaluate to true if the Content-Type is undefined
  84. // or unrecognized,such as when XDomainRequest has been used to
  85. // send the request.
  86. if (isset($HTTP_RAW_POST_DATA)) {
  87. parse_str($HTTP_RAW_POST_DATA,$_POST);
  88. }
  89.  
  90. if ($_POST['_method'] != null) {
  91. return $_POST['_method'];
  92. }
  93.  
  94. return $_SERVER['REQUEST_METHOD'];
  95. }
  96.  
  97. // Only needed in cross-origin setups
  98. function handleCorsRequest()
  99. {
  100. // If you are relying on CORS,you will need to adjust the allowed domain here.
  101. header('Access-Control-Allow-Origin: http://www.roughdrag.com');
  102. }
  103.  
  104. // Only needed in cross-origin setups
  105. function handlePreflight()
  106. {
  107. handleCorsRequest();
  108. header('Access-Control-Allow-Methods: POST');
  109. header('Access-Control-Allow-Headers: Content-Type');
  110. }
  111.  
  112. function getS3Client()
  113. {
  114. global $serverPublicKey,$serverPrivateKey;
  115.  
  116. return S3Client::factory(array(
  117. 'key' => $serverPublicKey,'secret' => $serverPrivateKey
  118. ));
  119. }
  120.  
  121. // Only needed if the delete file feature is enabled
  122. function deleteObject()
  123. {
  124. getS3Client()->deleteObject(array(
  125. 'Bucket' => $_POST['bucket'],'Key' => $_POST['key']
  126. ));
  127. }
  128.  
  129. function signRequest()
  130. {
  131. header('Content-Type: application/json');
  132.  
  133. $responseBody = file_get_contents('PHP://input');
  134. $contentAsObject = json_decode($responseBody,true);
  135. $jsonContent = json_encode($contentAsObject);
  136.  
  137. $headeRSStr = $contentAsObject["headers"];
  138. if ($headeRSStr) {
  139. signRestRequest($headeRSStr);
  140. } else {
  141. signPolicy($jsonContent);
  142. }
  143. }
  144.  
  145. function signRestRequest($headeRSStr)
  146. {
  147. if (isValidRestRequest($headeRSStr)) {
  148. $response = array('signature' => sign($headeRSStr));
  149. echo json_encode($response);
  150. } else {
  151. echo json_encode(array("invalid" => true));
  152. }
  153. }
  154.  
  155. function isValidRestRequest($headeRSStr)
  156. {
  157. global $expectedBucketName;
  158.  
  159. $pattern = "/\/$expectedBucketName\/.+$/";
  160. preg_match($pattern,$headeRSStr,$matches);
  161.  
  162. return count($matches) > 0;
  163. }
  164.  
  165. function signPolicy($policyStr)
  166. {
  167. $policyObj = json_decode($policyStr,true);
  168.  
  169. if (isPolicyValid($policyObj)) {
  170. $encodedPolicy = base64_encode($policyStr);
  171. $response = array('policy' => $encodedPolicy,'signature' => sign($encodedPolicy));
  172. echo json_encode($response);
  173. } else {
  174. echo json_encode(array("invalid" => true));
  175. }
  176. }
  177.  
  178. function isPolicyValid($policy)
  179. {
  180. global $expectedMaxSize,$expectedBucketName;
  181.  
  182. $conditions = $policy["conditions"];
  183. $bucket = null;
  184. $parsedMaxSize = null;
  185.  
  186. for ($i = 0; $i < count($conditions); ++$i) {
  187. $condition = $conditions[$i];
  188.  
  189. if (isset($condition["bucket"])) {
  190. $bucket = $condition["bucket"];
  191. } else if (isset($condition[0]) && $condition[0] == "content-length-range") {
  192. $parsedMaxSize = $condition[2];
  193. }
  194. }
  195.  
  196. return $bucket == $expectedBucketName && $parsedMaxSize == (string)$expectedMaxSize;
  197. }
  198.  
  199. function sign($stringToSign)
  200. {
  201. global $clientPrivateKey;
  202.  
  203. return base64_encode(hash_hmac(
  204. 'sha1',$stringToSign,$clientPrivateKey,true
  205. ));
  206. }
  207.  
  208. // This is not needed if you don't require a callback on upload success.
  209. function verifyFileInS3()
  210. {
  211. global $expectedMaxSize;
  212.  
  213. $bucket = $_POST["bucket"];
  214. $key = $_POST["key"];
  215.  
  216. // If utilizing CORS,we return a 200 response with the error message in the body
  217. // to ensure Fine Uploader can parse the error message in IE9 and IE8,// since XDomainRequest is used on those browsers for CORS requests. XDomainRequest
  218. // does not allow access to the response body for non-success responses.
  219. if (getObjectSize($bucket,$key) > $expectedMaxSize) {
  220. // You can safely uncomment this next line if you are not depending on CORS
  221. //header("HTTP/1.0 500 Internal Server Error");
  222. deleteObject();
  223. echo json_encode(array("error" => "Your file is too big!"));
  224. } else {
  225. echo json_encode(array("tempLink" => getTempLink($bucket,$key)));
  226. }
  227. }
  228.  
  229. // Provide a time-bombed public link to the file.
  230. function getTempLink($bucket,$key)
  231. {
  232. $client = getS3Client();
  233. $url = "{$bucket}/{$key}";
  234. $request = $client->get($url);
  235.  
  236. return $client->createPresignedUrl($request,'+15 minutes');
  237. }
  238.  
  239. function getObjectSize($bucket,$key)
  240. {
  241. $objInfo = getS3Client()->headObject(array(
  242. 'Bucket' => $bucket,'Key' => $key
  243. ));
  244. return $objInfo['ContentLength'];
  245. }
  246.  
  247. ?>

Amazon S3 CORS配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  3. <CORSRule>
  4. <AllowedOrigin>*</AllowedOrigin>
  5. <AllowedMethod>POST</AllowedMethod>
  6. <AllowedMethod>PUT</AllowedMethod>
  7. <AllowedMethod>DELETE</AllowedMethod>
  8. <MaxAgeSeconds>3000</MaxAgeSeconds>
  9. <ExposeHeader>ETag</ExposeHeader>
  10. <AllowedHeader>*</AllowedHeader>
  11. </CORSRule>
  12. </CORSConfiguration>

IAM集团安全政策

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

uploader.js是从http://fineuploader.com/source/all.fineuploader-3.9.1.min.js捕获的

控制台响应

  1. [FineUploader 3.9.0-3] Grabbed 1 dropped files.
  2.  
  3. [FineUploader 3.9.0-3] Received 1 files or inputs.
  4.  
  5. [FineUploader 3.9.0-3] Submitting S3 signature request for 0
  6.  
  7. [FineUploader 3.9.0-3] Sending POST request for 0
  8.  
  9. POST http://www.roughdrag.com/handlers/uploadHandler.PHP 200 OK 195ms
  10.  
  11. [FineUploader 3.9.0-3] Sending upload request for 0
  12.  
  13. POST http://upload.roughdrag.com/ 405 Method Not Allowed 559ms
  14.  
  15. "NetworkError: 405 Method Not Allowed - http://upload.roughdrag.com/"
  16.  
  17. [FineUploader 3.9.0-3] Received response status 405 with body: <html>
  18. <head><title>405 Method Not Allowed</title></head>
  19. <body>
  20. <h1>405 Method Not Allowed</h1>
  21. <ul>
  22. <li>Code: MethodNotAllowed</li>
  23. <li>Message: The specified method is not allowed against this resource.</li>
  24. <li>ResourceType: OBJECT</li>
  25. <li>Method: POST</li>
  26. <li>RequestId: 3493FE605B461EAF</li>
  27. <li>HostId: HDXmtSpHufy6LDIH1Nsp0oYkLDvTC3XKFRRIadw66gmaMsF53Z3WYsCWooOoRcw2</li>
  28. </ul>
  29. <hr/>
  30. </body>
  31. </html>
  32.  
  33. [FineUploader 3.9.0-3] Waiting 5 seconds before retrying breakout.jpg...
  34.  
  35. [FineUploader 3.9.0-3] Detected valid cancel,retry,or delete click event on file 'breakout.jpg',ID: 0.
  36.  
  37. [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请求.

猜你在找的PHP相关文章