gpt4 book ai didi

php - 无法显示由 fine-uploader 上传到 Amazon s3 的图像

转载 作者:可可西里 更新时间:2023-11-01 01:02:59 25 4
gpt4 key购买 nike

我现在正在尝试设置 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"
}

到我的 javascript 文件中的 fine-uploader 实例,这样临时链接应该由 s3demo.php 文件中的函数生成。

我意识到我必须安装 AWS SDK 才能让它工作。安装的 zip 方法真的不起作用,所以我使用 phar。我将 s3demo.php 文件的那部分更改为:

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

我还取消了这两行的注释:

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

我在让它工作时遇到了两个问题。第一个是我从 AWS 的成功响应出了问题,我认为我应该从 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/*”
}]
}

第二个问题是如何在我的 javascript 中访问由 s3demo.php 生成的 json 数组,以便显示上传的图像,我确信我应该能够弄清楚但不能。我想这不是 $templink[0]。我想知道是否可以看到在 http://fineuploader.com/#s3-demo 上提供查看按钮的示例代码它的功能。如果我应该在这里提出第二个问题,我很乐意这样做。

非常感谢您的宝贵时间。

编辑以按要求添加我的完整代码:

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。我在这个测试中使用了 Mark 在 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"

}
});
});

最佳答案

听起来您只是想模仿 FineUploader.com 上 S3 演示的行为。因此,您显然遇到麻烦的部分是允许您查看/下载已上传文件的演示部分。我的猜测是您没有设置 PARAM1PARAM2 环境变量。您真的应该看看 PHP 文档中的 $_SERVER super 全局是如何工作的。就目前而言,此代码期望您有一个名为 PARAM1 的系统环境变量,该变量保存与您应该为服务器(而非客户端)创建的 IAM 用户相关联的公共(public) AWS key 。 PARAM2 系统环境变量应设置为同一用户的 key 。您可以设置这些环境变量,或将关联的 $serverPublicKey$serverPrivateKey PHP 全局变量分别设置为服务器端 IAM 用户的公钥和私钥。

请注意,与服务器的 AWS 公钥和私钥(PARAM1PARAM2)关联的系统环境变量的名称选择不当是由于服务器对于 fineuploader.com S3 演示正在 AWS EC2 instance 上运行由 Amazon's Elastic Beanstalk service 创建. Elastic Beanstalk 不提供(至少它显然不提供)通过 PHP 应用程序的 Elastic Beanstalk UI 命名系统环境变量的方法。它将它们命名为 PARAM1PARAM2 等。

$serverPublicKey$serverPrivateKey 变量不应与您为客户端任务创建的 IAM 用户关联的 key 相同。您应该已经创建了一个具有适用于服务器端任务的权限的不同 IAM 用户。例如,如果您想要支持删除文件功能,您可能希望拥有一个具有“S3:DeleteObject”权限的 IAM 用户。出于安全原因,此用户应仅限于服务器端任务。

在您的情况下,您的服务器端 IAM 用户必须对您的存储桶具有“S3:GetObject”权限。需要此权限才能从您的存储桶中获取对象。最安全的方法是仅将此权限授予您的服务器端 IAM 用户。您可能会问:“如果我的客户端用户无法从我的存储桶中读取对象,我该如何允许客户端下载文件?”好吧,一种选择是将 Fine Uploader 中的 acl 选项设置为“public-read”,然后使用此约定构建客户端 URL:“http://mybucket.s3.amazonaws.com/objectkey”。这不是 fineuploader.com 上的 S3 演示的工作方式。继续阅读以了解详细信息...

我不想让用户无限制地访问他们上传到 Fine Uploader 的 S3 存储桶中的文件,所以我将 acl 保留为“private”(默认值),我只给了我的服务器-side IAM 用户“S3:GetObject”对 Fine Uploader S3 存储桶的权限,我让服务器返回一个“定时炸弹”签名 URL 到存储桶中的关联对象。服务器返回的 URL 包含一个过期参数,只允许使用 15 分钟。任何更改查询字符串中的过期参数的尝试都会使签名无效并且请求将失败。 PHP 示例中的 getTempLink 函数将生成一个定时签名的 URL,该 URL 在对 Fine Uploader 的 uploadSucess.endpoint POST 请求的响应中返回。您可以通过贡献一个 complete event handler 来访问这个值.传递给回调的 responseJSON 对象参数将包含一个包含签名 URL 的 tempLink 属性。然后,您可以生成一个 anchor ,并将 src 属性设置为此属性的值。

关于php - 无法显示由 fine-uploader 上传到 Amazon s3 的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18369235/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com