我现在正在尝试设置 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->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->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->processMessages()
#3 phar:///MYSITE//aws.phar/Guzzle/Http/Curl/CurlMulti.php(212): Guzzle\Http\Curl\CurlMulti->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 演示的行为。因此,您显然遇到麻烦的部分是允许您查看/下载已上传文件的演示部分。我的猜测是您没有设置 PARAM1 和 PARAM2 环境变量。您真的应该看看 PHP 文档中的 $_SERVER super 全局是如何工作的。就目前而言,此代码期望您有一个名为 PARAM1 的系统环境变量,该变量保存与您应该为服务器(而非客户端)创建的 IAM 用户相关联的公共(public) AWS key 。 PARAM2 系统环境变量应设置为同一用户的 key 。您可以设置这些环境变量,或将关联的 $serverPublicKey 和 $serverPrivateKey PHP 全局变量分别设置为服务器端 IAM 用户的公钥和私钥。
请注意,与服务器的 AWS 公钥和私钥(PARAM1 和 PARAM2)关联的系统环境变量的名称选择不当是由于服务器对于 fineuploader.com S3 演示正在 AWS EC2 instance 上运行由 Amazon's Elastic Beanstalk service 创建. Elastic Beanstalk 不提供(至少它显然不提供)通过 PHP 应用程序的 Elastic Beanstalk UI 命名系统环境变量的方法。它将它们命名为 PARAM1、PARAM2 等。
$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/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article