возникли проблемы с отображением изображения, загруженного в Amazon s3, с помощью тонкой загрузки

Теперь я пытаюсь настроить fineuploader-s3, чтобы показать изображение файла, успешно загруженного на сервер aws, как это было сделано на странице примера здесь: http://fineuploader.com/#s3-demo

Я (по-прежнему) использую код на https://github.com/Widen/fine-uploader-server/blob/master/php/s3/s3demo.php , и я добавил

uploadSuccess: { endpoint: "s3demo.php?success" } 

к экземпляру fine-uploader в моем javascript-файле, так что временная ссылка должна быть сгенерирована функцией в файле s3demo.php.

Я понял, что мне пришлось установить AWS SDK, чтобы заставить это работать. Метод установки zip действительно не работал, поэтому я использую phar. Я изменил этот раздел файла s3demo.php на:

 require 'aws.phar'; use Aws\S3\S3Client; 

Я также раскупил эти две строки:

 $serverPublicKey = $_SERVER['PARAM1']; $serverPrivateKey = $_SERVER['PARAM2']; 

У меня возникают две проблемы, связанные с тем, чтобы это работало. Во-первых, что-то не так с моим успехом от AWS, из которого я думаю, что я должен получить ссылку на файл.

Файл загружается отлично, но я получаю сообщение об ошибке в консоли:

 [FineUploader 3.8.0] Sending POST request for 0 s3.jquery.fineuploader-3.8.0.js:164 [FineUploader 3.8.0] Received the following response body to an AWS upload success request for id 0: <br /> <b>Fatal error</b>: Uncaught exception 'Guzzle\Http\Exception\CurlException' with message '[curl] 28: Connection timed out after 1001 milliseconds [url] http://169.254.169.254/latest/meta-data/iam/security-credentials/' in phar:///MYSITE/aws.phar/Guzzle/Http/Curl/CurlMulti.php:339 Stack trace: #0 phar:///MYSITE//aws.phar/Guzzle/Http/Curl/CurlMulti.php(280): Guzzle\Http\Curl\CurlMulti-&gt;isCurlException(Object(Guzzle\Http\Message\Request), Object(Guzzle\Http\Curl\CurlHandle), Array) #1 phar:///MYSITE//aws.phar/Guzzle/Http/Curl/CurlMulti.php(245): Guzzle\Http\Curl\CurlMulti-&gt;processResponse(Object(Guzzle\Http\Message\Request), Object(Guzzle\Http\Curl\CurlHandle), Array) #2 phar:///MYSITE//aws.phar/Guzzle/Http/Curl/CurlMulti.php(228): Guzzle\Http\Curl\CurlMulti-&gt;processMessages() #3 phar:///MYSITE//aws.phar/Guzzle/Http/Curl/CurlMulti.php(212): Guzzle\Http\Curl\CurlMulti-&gt;executeHandles() #4 phar:///MYSITE/z/aw in <b>phar:///home/nextq2/public_html/lenz/aws.phar/Aws/Common/InstanceMetadata/InstanceMetadataClient.php</b> on line <b>82</b><br /> s3.jquery.fineuploader-3.8.0.js:164 [FineUploader 3.8.0] Upload success was acknowledged by the server. s3.jquery.fineuploader-3.8.0.js:164 

Означает ли это, что что-то не так с моей установкой AWS SDK или в моих настройках разрешений на Amazon? Для настроек CORS и IAM? Которые все еще выглядят следующим образом:

 <CORSRule> <AllowedOrigin>MY WEBSITE</AllowedOrigin> <AllowedMethod>POST</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>*</AllowedHeader> </CORSRule> 

Моя групповая политика в IAM:

  { "Version":"2012-10-17", "Statement":[{ "Effect":"Allow", "Action":"s3:PutObject", "Resource":"arn:aws:s3:::MY_BUCKET/*” }] } 

Вторая проблема, которая, я уверен, должна быть в состоянии выяснить, но не могу, – это получить доступ к массиву json, генерируемому s3demo.php, в моем javascript, чтобы я мог отображать загруженное изображение. Я думаю, что это не $ templink [0]. Мне было интересно, можно ли увидеть пример кода, который дает кнопку просмотра на http://fineuploader.com/#s3-demo его функции. Если мне стоит задать второй вопрос, я с удовольствием сделаю это.

Большое спасибо за ваше время.

EDIT, чтобы добавить мой полный код в соответствии с запросом:

PHP:

 <?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 = 'I put my private key here; // 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['PARAM1']; $serverPrivateKey = $_SERVER['PARAM2']; $expectedMaxSize = 15000000; $expectedBucket = “my bucket name here; $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") { // handlePreflightedRequest(); // 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') { handlePreflightedRequest(); // 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 handlePreflightedRequest() { // If you are relying on CORS, you will need to adjust the allowed domain here. //header('Access-Control-Allow-Origin: http://nextquestion.org'); } // Only needed in cross-origin setups function handlePreflight() { handlePreflightedRequest(); 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 $expectedBucket; $pattern = "/\/$expectedBucket\/.+$/"; 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, $expectedBucket; $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 == $expectedBucket && $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))); } } function testfunction(){ alert('whatever'); } // 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']; } ?> 

Мой html. Я использовал другой пример, который Марк имел в StackOverflow для этого теста, потому что в конце концов я хочу отправить некоторые другие данные одновременно:

 <!DOCTYPE html> <html> <head> <title>test of fine uploader</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="fineuploader-3.8.0.css" rel="stylesheet"> <style> .button { display: block; height: 30px; width: 100px; border: 1px solid #000; } </style> <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> <script src="s3.jquery.fineuploader-3.8.0.js"></script> <script type="text/javascript" src="lenz_javascript4.js"></script> </head> <body> <!-- Generated Image Thumbnail --> <a href="#" id="thumbnail">view image</a> <form action="fineuploadertest.php" method="post" id="uploader"> <input type="text" name="textbox" value="Test data"> <div id="manual-fine-uploader"></div> <div id="triggerUpload" class="button" style="margin-top: 10px;">click here </div> </form> </body> </html> 

Мой javascript:

 $(document).ready(function() { $("#triggerUpload").click(function () { $("#manual-fine-uploader").fineUploaderS3('uploadStoredFiles'); }); function submitForm () { if ($(this).fineUploader('getInProgress') == 0) { var failedUploads = $(this).fineUploaderS3('getUploads', { status: qq.status.UPLOAD_FAILED }); if (failedUploads.length == 0) { // do any other form processing here $("#uploader").submit(); } } }; $("#manual-fine-uploader").fineUploaderS3({ autoUpload: false, debug: true, request: { endpoint: "http://my bucket name.s3.amazonaws.com", accessKey: “I put my access key here” }, validation: { allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'], sizeLimit: 15000000, itemLimit: 3 }, signature: { endpoint: "s3demo.php" }, camera: { ios: true }, iframeSupport: { localBlankPagePath: "/success.html" }, uploadSuccess: { endpoint: "s3demo.php?success" } }); }); 

    Похоже, вы просто хотите отразить поведение демонстрации S3 на FineUploader.com. Итак, у части, с которой вы, по-видимому, возникают проблемы, является часть демонстрации, которая позволяет вам просматривать / загружать загруженный файл. Я предполагаю, что вы не устанавливаете переменные окружения PARAM1 и PARAM2 . Вы действительно должны посмотреть, как супер-глобальный $_SERVER работает в документации PHP. Этот код, как он есть, ожидает, что у вас будет переменная системной среды с именем PARAM1 которая содержит общедоступный AWS-ключ, связанный с пользователем IAM, который вы должны создать для своего сервера (а не вашего клиента). PARAM2 системной среды PARAM2 должна быть установлена ​​на секретный ключ для этого же пользователя. Вы можете либо установить эти переменные среды, либо установить связанные глобальные переменные $serverPublicKey и $serverPrivateKey PHP на общедоступные и секретные ключи пользователя IAM на стороне сервера, соответственно.

    Обратите внимание, что неправильный выбор имени для переменных системной среды, связанных с общедоступным и секретным ключом AWS сервера ( PARAM1 и PARAM2 ), связан с тем, что сервер для демонстрации Fineploader.com S3 работает на экземпляре AWS EC2, созданном Amazon's Упругий бобслей . Эластичный Beanstalk не предоставляет (по крайней мере, это явно не дает) способ назвать переменные системной среды через UI-интерфейс для использования PHP-приложений. Он называет их PARAM1 , PARAM2 и т. Д.

    $serverPublicKey и $serverPrivateKey НЕ должны быть теми же ключами, которые связаны с пользователем IAM, созданным для задач на стороне клиента. Вы должны создать другого пользователя IAM с разрешениями, подходящими для задач на стороне сервера. Например, если вы хотите поддерживать функцию файла удаления, вы хотели бы иметь пользователя IAM с разрешением «S3: DeleteObject». Этот пользователь должен быть ограничен задачами на стороне сервера только по соображениям безопасности.

    В вашем случае ваш пользователь IAM на стороне сервера должен иметь разрешение «S3: GetObject» на вашем ковше. Это разрешение требуется для получения объектов из вашего ведра. Самый безопасный подход заключается в предоставлении этого разрешения только для пользователя IAM на стороне сервера. Вероятно, вы спрашиваете: «Если мой клиентский пользователь не может читать объект из моего ведра, как разрешить загрузку файла на стороне клиента?» Ну, один из вариантов заключается в том, чтобы установить параметр acl в Fine Uploader на «public-read», а затем сконструировать клиентскую часть URL, используя это соглашение: « http://mybucket.s3.amazonaws.com/objectkey ». Это НЕ способ, которым работает демонстрация S3 на сайте fineuploader.com. Читайте подробнее …

    Я не хотел предоставлять пользователям неограниченный доступ к файлам, которые они загружали в ведомый файл Fine3, поэтому я оставил acl «private» (значение по умолчанию), я дал только пользователю IAM на стороне сервера «S3: GetObject» в ящик Fine Uploader S3, и у меня есть сервер, который возвращает «связанный с бомбой» подписанный URL-адрес связанного объекта в ведре. URL-адрес, возвращаемый сервером, содержит параметр срока действия, который позволяет использовать его только 15 минут. Любые попытки изменить этот параметр истечения в строке запроса аннулируют подпись, и запрос будет терпеть неудачу. Функция getTempLink в примере PHP будет генерировать подписанный по времени URL-адрес, который возвращается в ответ на uploadSucess.endpoint POST для uploadSucess.endpoint . Вы можете получить доступ к этому значению, предоставив complete обработчик событий . Параметр объекта responseJSON переданный в ваш обратный вызов, будет содержать свойство tempLink которое будет содержать подписанный URL. Затем вы можете создать привязку с атрибутом src установленным для значения этого свойства.