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 91
I am getting the above error whenever I run my multipart upload program use AWS S3. My program should slice part of the file in a JS script that is then sent to a php script using XMLHTTPRequest. That part seems to be working well. However, the issue arises when CompleteMultipartUpload is called. What I gather from the error is that my part are too small or are empty.
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;
}
Is there anything that is obviously wrong on how I am accomplishing my task. My only thought would be that my part size it too small for the upload. If that is the case, I do have a work around for that with another version of my project that I have been working on.
s3:ObjectCreated:CompleteMultipartUpload – An object was created by the completion of a S3 multi-part upload. s3:ObjectCreated:* – An object was created by one of the event types listed above or by a similar object creation event added in the future.
PDF. Completes a multipart upload by assembling previously uploaded parts. You first initiate the multipart upload and then upload all parts using the UploadPart operation.
You are working with the S3 API and receive an error: 409 Conflict. What is a possible cause of this error? You're attempting to delete a bucket without first removing the contents in the bucket. Explanation: A 409 HTTP Status Code can indicate a BucketNotEmpty error code.
I just spend a few too many minutes* on this same problem, until I realized that the Parts argument should be nested in a MultipartUpload entry. My code now looks like this:
$completeParams = Array(
'Bucket' => $multipartUpload['Bucket'],
'Key' => $multipartUpload['Key'],
'MultipartUpload' => Array(
'Parts' => $parts,
),
'UploadId' => $multipartUpload['UploadId']
);
$res = $client->completeMultipartUpload($completeParams);
And that works just fine. At least when using version 3 of the SDK. Version 2 of the SDK expects Parts directly in $params.
*I won't reveal how many minutes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With