【问题标题】:Aws S3 CompleteMultipartUpload errorAws S3 CompleteMultipartUpload 错误
【发布时间】:2015-08-03 17:25:16
【问题描述】:

致命错误:未捕获的 Aws\S3\Exception\InvalidRequestException:AWS 错误代码:InvalidRequest,状态代码:400,AWS 请求 ID:B1A28EBE65521DF4,AWS 错误类型:客户端,AWS 错误消息:您必须指定至少一个部分,用户代理:aws-sdk-php2/2.7.22 Guzzle/3.9.2 curl/7.40.0 PHP/5.6.6 在 C:\vhosts********.com\db**** 中抛出*\FileUploader_v2\aws\Aws\Common\Exception\NamespaceExceptionFactory.php 第 91 行

每当我使用 AWS S3 运行分段上传程序时,我都会收到上述错误。我的程序应该在 JS 脚本中分割文件的一部分,然后使用 XMLHTTPRequest 将其发送到 php 脚本。这部分似乎运作良好。但是,调用 CompleteMultipartUpload 时会出现问题。我从错误中收集到的是我的部分太小或为空。

上传.htm

var command; var file; var ownerName; var totalSize; var partSize = 2 * 1024 * 1024; // constant var sendBackData; var totalSize; var sureUploadSize = 0, probableUplaodSize = 0; var numParts; var partsLeft = [];

    function _(el){
        return document.getElementById(el);
    }

    function calcTotalSize(file){
        var size_total = 0;
        for(var i = 0; i < file.length; i++){
            size_total += file[i].size;
        }
        return size_total;
    }

    function uploadFile(){
        file = _("file").files[0];
        console.log(file);
        ownerName = _("name").value;
        totalSize = file.size;
        command = 'CreateMultipartUpload';

        var formdata = new FormData();
        formdata.append("command", command);
        formdata.append("filename", file.name);
        formdata.append("name", ownerName);
        var ajax = new XMLHttpRequest();
        ajax.open("POST", "FileUploader.php", true);
        ajax.send(formdata);
        ajax.onreadystatechange = function() {
            if (ajax.readyState === 4) {
                sendBackData = JSON.parse(ajax.responseText);
                numParts = Math.ceil(totalSize / partSize);
                uploadPart(1);
            }
        };
    }

    function uploadPart(partNum){
        console.log("Uploading part " + partNum);
        console.log(sendBackData['uploadId']);
        command = 'UploadPart';

        if (partNum > numParts) {
            completeMultipartUpload();
            return;
        }

        var formdata = new FormData();

        var start = (partNum - 1) * partSize;
        var end = start + partSize;
        if (end > totalSize)
            end = totalSize;
        var length = end - start;
        var curBlobPart = file.slice(start, end);

        //console.log(sendBackData['uploadId']);

        formdata.append("file[]", curBlobPart);
        formdata.append("command", command);
        formdata.append("uploadId", sendBackData['uploadId']);
        formdata.append("key", sendBackData['key']);
        formdata.append("partNumber", partNum);

        var ajax = new XMLHttpRequest();
        ajax.open("POST", "FileUploader.php", true);
        ajax.addEventListener("load", completeHandler, false);
        ajax.addEventListener("error", errorHandler, false);
        ajax.addEventListener("abort", abortHandler, false);
        ajax.send(formdata);
        ajax.onreadystatechange = function() {
            if (ajax.readyState === 4) {
                uploadPart(partNum + 1);
            }
        };
    }

    function completeMultipartUpload() {
        command = 'CompleteMultipartUpload';

        var formdata = new FormData();
        formdata.append("command", command);
        formdata.append("uploadId", sendBackData['uploadId']);
        formdata.append("key", sendBackData['key']);

        var ajax = new XMLHttpRequest();
        ajax.open("POST", "FileUploader.php", true);
        ajax.addEventListener("load", completeHandler, false);
        ajax.addEventListener("error", errorHandler, false);
        ajax.addEventListener("abort", abortHandler, false);
        ajax.send(formdata);
        ajax.onreadystatechange = function() {
            if (ajax.readyState === 4) {
                alert("File uploaded successfully");
            }
        };
    }

    function progressHandler(event){
        _("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
        var percent = (event.loaded / event.total) * 100;
        _("progressBar").value = Math.round(percent);
        _("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
    }
    function completeHandler(event){
        _("status").innerHTML = event.target.responseText;
        _("progressBar").value = 0;
    }
    function errorHandler(event){
        _("status").innerHTML = "Upload Failed";
    }
    function abortHandler(event){
        _("status").innerHTML = "Upload Aborted";
    }`

文件上传器.php: `

//require 'SimpleImage.php';
//require 'gifsplit.php';
//require 'functions.php';

require 'config.php';
require 'aws/aws-autoloader.php';

use Aws\Common\Exception\MultipartUploadException;
use Aws\S3\Model\MultipartUpload\UploadBuilder;
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;

function sendJson($arr)
{
    header('Content-Type: application/json');
    die(json_encode($arr));
}

// S3
$s3 = S3Client::factory(array(
    'key' => AWS_KEY,
    'secret' => AWS_SECRET_KEY
));

//$part = $_POST['part'];

switch ($_POST['command']) {
    case 'CreateMultipartUpload':
        $key = "other/".$_POST['name']."/".$_POST['filename'];

        $response = $s3->createMultipartUpload(array(
            'Bucket'    => TMP_IMG,
            'Key'       => $key
        ));

        $uploadId = $response['UploadId'];

        sendJson(array(
            'uploadId' => $uploadId,
            'key'      => $key
        ));
        break;

    case 'UploadPart':
        var_dump($_FILES['file']);

        $result = $s3->uploadPart(array(
            'Bucket'    => TMP_IMG,
            'Key'       => $_POST['key'],
            'UploadId'  => $_POST['uploadId'],
            'PartNumber'=> $_POST['partNumber'],
            'Body'      => $_FILES['file']['tmp_name']
        ));
        break;

    case 'CompleteMultipartUpload':
        $partsModel = $s3->listParts(array(
            'Bucket' => TMP_IMG,
            'Key'       => $_POST['key'],
            'UploadId'  => $_POST['uploadId']
        ));

        $model = $s3->completeMultipartUpload(array(
            'Bucket' => TMP_IMG,
            'Key' => $_POST['key'],
            'UploadId' => $_POST['uploadId'],
            'Parts' => $partsModel['Parts']
        ));

        sendJson(array(
            'success' => true
        ));
        break;

    case 'AbortMultipartUpload':
        # code...
        break;

    default:
        # code...
        break;
}

在我完成任务的方式上有什么明显的错误吗?我唯一的想法是我的零件尺寸太小而无法上传。如果是这种情况,我确实可以使用我一直在处理的另一个版本的项目来解决这个问题。

【问题讨论】:

    标签: php amazon-web-services file-upload amazon-s3 filesize


    【解决方案1】:

    我只是在同样的问题上花费了几分钟*,直到我意识到 Parts 参数应该嵌套在 MultipartUpload 条目中。我的代码现在看起来像这样:

    $completeParams = Array(
        'Bucket' => $multipartUpload['Bucket'],
        'Key' => $multipartUpload['Key'],
        'MultipartUpload' => Array(
            'Parts' => $parts,
        ),
        'UploadId' => $multipartUpload['UploadId']
    );
    
    $res = $client->completeMultipartUpload($completeParams);
    

    而且效果很好。至少在使用 SDK 版本 3 时。 SDK 的第 2 版需要直接在 $params 中的 Parts。

    *我不会透露多少分钟

    【讨论】:

    • 这真的很有帮助 - 文档或示例都没有提到这一点!
    猜你喜欢
    • 2011-10-30
    • 2012-05-02
    • 2017-08-10
    • 2018-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-06
    • 2016-11-02
    相关资源
    最近更新 更多