2015-05-21 22 views
6

Fatal error: Uncaught Aws\S3\Exception\InvalidRequestException: AWS Error Code: InvalidRequest, Status Code: 400, AWS Request ID: B1A28EBE65521DF4, AWS Error Type: client, AWS Error Message: You must specify at least one part, User-Agent: aws-sdk-php2/2.7.22 Guzzle/3.9.2 curl/7.40.0 PHP/5.6.6 thrown in C:\vhosts********.com\db*****\FileUploader_v2\aws\Aws\Common\Exception\NamespaceExceptionFactory.php on line 91Aws S3 CompleteMultipartLỗi tải lên

Tôi nhận được lỗi ở trên bất cứ khi nào tôi chạy chương trình tải lên nhiều phần của mình sử dụng AWS S3. Chương trình của tôi nên cắt một phần của tập tin trong một kịch bản JS mà sau đó được gửi đến một kịch bản php bằng cách sử dụng XMLHTTPRequest. Phần đó dường như hoạt động tốt. Tuy nhiên, vấn đề phát sinh khi CompleteMultipartUpload được gọi. Những gì tôi thu thập từ lỗi là phần của tôi quá nhỏ hoặc trống.

upload.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"; 
    }` 

FileUploader.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; 
} 

Có điều gì đó rõ ràng là sai về cách tôi đang hoàn thành của tôi bài tập. Suy nghĩ duy nhất của tôi là phần của tôi có kích thước quá nhỏ để tải lên. Nếu đúng như vậy, tôi có một công việc xung quanh cho điều đó với một phiên bản khác của dự án mà tôi đang làm.

Trả lời

11

Tôi chỉ mất vài phút * trên cùng một vấn đề này, cho đến khi tôi nhận ra rằng tham số Phần nên được lồng trong mục nhập MultipartUpload. Mã của tôi bây giờ trông giống như sau:

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

$res = $client->completeMultipartUpload($completeParams); 

Và nó hoạt động tốt. Ít nhất là khi sử dụng phiên bản 3 của SDK. Phiên bản 2 của SDK mong đợi các phần trực tiếp trong tham số $.

* Tôi sẽ không tiết lộ số phút

+1

Điều này thực sự hữu ích - không có tài liệu hoặc ví dụ nào đề cập đến điều đó! – benJ

+0

hoàn hảo cảm ơn bạn –

Các vấn đề liên quan