php - 将 Amazon S3 与 FineUploader 结合使用时出错

标签 php javascript zend-framework amazon-s3 fine-uploader

我正在尝试使用 Amazon S3 来存储我的文件。我还想使用 FineUploader 将图像上传到亚马逊(我正在使用 Zend Framework)。

这是我的观点:

<div id="fineuploader-s3"></div>

这是我的 javascript 文件:(更改的键/存储桶名称)

$(document).ready(function () {
$('#fineuploader-s3').fineUploaderS3({
    request: {
        // REQUIRED: We are using a custom domain
        // for our S3 bucket, in this case.  You can
        // use any valid URL that points to your bucket.
        endpoint: "mybucket.s3.amazonaws.com",

        // REQUIRED: The AWS public key for the client-side user
        // we provisioned.
        accessKey: "mykey"
    },

    // REQUIRED: Path to our local server where requests
    // can be signed.
    signature: {
        endpoint: "/s3/s3demo.php"
    },

    // OPTIONAL: An endopint for Fine Uploader to POST to
    // after the file has been successfully uploaded.
    // Server-side, we can declare this upload a failure
    // if something is wrong with the file.
    uploadSuccess: {
        endpoint: "/s3demo.php?success"
    },

    // USUALLY REQUIRED: Blank file on the same domain
    // as this page, for IE9 and older support.
    iframeSupport: {
        localBlankPagePath: "/server/success.html"
    },

    // optional feature
    retry: {
        showButton: true
    },

    // optional feature
    chunking: {
        enabled: true
    },

    // optional feature
    resume: {
        enabled: true
    },

    // optional feature
    deleteFile: {
        enabled: true,
        method: "POST",
        endpoint: "/s3demo.php"
    },

    // optional feature
    validation: {
        itemLimit: 5,
        sizeLimit: 15000000
    }
});
});

这是我在文件夹 s3 中的“s3demo.php”文件(在公共(public)文件中,根文件中):(更改了 key /存储桶名称)

<?php

// You can remove these two lines if you are not using Fine Uploader's
// delete file feature
require 'AWSSDKforPHP/aws.phar';
use Aws\S3\S3Client;

// These assume you have the associated AWS keys stored in
// the associated system environment variables
$clientPrivateKey = $_SERVER['mykey'];
// 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'];

// The following variables are used when validating the policy document
// sent by the uploader. 
$expectedBucketName = "mybucket.s3.amazonaws.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 = null;

$method = getRequestMethod();

// This second conditional will only ever evaluate to true if
// the delete file feature is enabled
if ($method == "DELETE") {
    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') {

    // 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() {

    if ($_POST['_method'] != null) {
        return $_POST['_method'];
    }

    return $_SERVER['REQUEST_METHOD'];
}

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" => "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'];
}
?>

我得到这个错误:

[FineUploader 3.8.0] Error attempting to parse signature response: SyntaxError: Unexpected token < s3.jquery.fineuploader-3.8.0.min.js:16
[FineUploader 3.8.0] Received an empty or invalid response from the server! s3.jquery.fineuploader-3.8.0.min.js:16
[FineUploader 3.8.0] Policy signing failed. Received an empty or invalid response from the server! s3.jquery.fineuploader-3.8.0.min.js:16

第一个错误显示我的 s3demo.php 文件有问题...(标记 < -> 我的 php 文件的第一个)

响应 - 标题:

Request URL:http://www.link.com/s3/s3demo.php
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:/
Accept-Encoding:gzip,deflate,sdch
Accept-Language:nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:no-cache
Connection:keep-alive
Content-Length:292
Content-Type:application/json; charset=UTF-8
Cookie:PHPSESSID=
Host:www.link.com
Origin:http://www.link.com
Pragma:no-cache
Referer:http://www.link.com/quiz/design
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36
Request Payloadview source
{expiration:2013-08-28T15:35:56.160Z,…}
conditions: [{acl:private}, {bucket:mybucket}, {Content-Type:image/png}, {success_action_status:200},…] expiration: "2013-08-28T15:35:56.160Z"
Response Headers view source
Connection:Keep-Alive
Content-Length:2504
Content-Type:application/json
Date:Wed, 28 Aug 2013 15:30:55 GMT
Keep-Alive:timeout=5, max=90
Server:Apache/2.2.22 (Debian)
X-Powered-By:PHP/5.5.1-1~dotdeb.1

实际响应:


( ! ) Notice: Undefined index: _method in /var/www/site/public/s3/s3demo.php on line 79 Call Stack #TimeMemoryFunctionLocation 10.0047235456{main}( )../s3demo.php:0 20.0323825744getRequestMethod( )../s3demo.php:48
( ! ) Notice: Undefined index: headers in s3/s3demo.php on line 110 Call Stack #TimeMemoryFunctionLocation 10.0047235456{main}( )../s3demo.php:0 20.0325825896signRequest( )../s3demo.php:67 {"invalid":true}

最佳答案

我认为您不太理解文档或示例。您需要一个服务器端组件来签署 Fine Uploader 发送的请求。出于某种原因,您似乎将 Fine Uploader 指向 JSON 文件。我猜你从博文中复制了示例签名文件,并指向 Fine Uploader?博客文章中详细介绍了示例签名文件,让您深入了解 Fine Uploader S3 如何为您生成简单上传的策略文档。您无需在任何地方存储此副本。

您至少需要一个适当的服务器端组件来签署 Fine Uploader 发送到 S3 的请求。 https://github.com/Widen/fine-uploader-server 中已有 5 个 Fine Uploader S3 的全功能服务器端示例.事实上,博客文章链接到用 node、python、php 和 java 编写的示例。您还应该更仔细地查看博客文章或文档。

关于php - 将 Amazon S3 与 FineUploader 结合使用时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18481123/

相关文章:

php - 使用 Zend_Db_Expr 选择 Zend DB

php - 如何构建一个将返回标志的 MySQL 查询,根据另一个表中的行返回 y 或 n?

php - 使用nodeMCU在mysql中写入dht11传感器失败

javascript - Angular Treel 控件中的多个叶节点禁用

Javascript SetInterval 带有警告

zend-framework - Zend框架-如何编写group by查询

php - 按多个属性选择产品,使用 AND 代替 OR 连接器,数据模型 EAV

php - 一个php容器上具有两个单独的php-services的docker

javascript - 将两种不同类型的 div 附加到单个容器

php - Zend Framework - 使用路由和正则表达式设置用户友好的 URL