2015-05-21 23 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 CompleteMultipartUpload error

Ricevo l'errore sopra riportato ogni volta che eseguo il mio programma di caricamento multipart utilizzando AWS S3. Il mio programma dovrebbe tagliare parte del file in uno script JS che viene poi inviato a uno script php usando XMLHTTPRequest. Questa parte sembra funzionare bene. Tuttavia, il problema sorge quando viene chiamato CompleteMultipartUpload. Quello che ho ricavato dall'errore è che la mia parte è troppo piccola o vuota.

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'è qualcosa che è ovviamente sbagliato su come sto compiendo il mio compito. Il mio unico pensiero sarebbe che la mia parte fosse troppo piccola per il caricamento. Se questo è il caso, ho una soluzione per questo con un'altra versione del mio progetto su cui ho lavorato.

risposta

11

Ho trascorso solo pochi minuti * su questo stesso problema, fino a quando ho realizzato che l'argomento Parti deve essere annidato in una voce MultipartUpload. Il mio codice ora è simile al seguente:

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

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

E funziona perfettamente. Almeno quando si utilizza la versione 3 dell'SDK. La versione 2 dell'SDK prevede le parti direttamente in $ param.

* Non rivelerò quanti minuti

+1

Questo è stato davvero utile - nessuno della documentazione o degli esempi lo menzionano! – benJ

+0

perfetto grazie –

Problemi correlati