I'm using Uppy's Vue components to handle uploading large files and I'm having trouble getting it to work.
I've followed the suggestion by Janko here which involves setting the companionUrl in Uppy to point to my server, then write the necessary routes/functions to process the requests.
Everything is working until I try to fire the AWS "completeMultipartUpload" call.
$result = $client->completeMultipartUpload([
'Bucket' => 'bucket-name',
'Key' => $key,
'UploadId' => $uploadId,
'MultipartUpload' => [
'Parts' => $formattedParts,
],
]);
I get the following error:
"Error executing "CompleteMultipartUpload" on "https://bucket-name.s3.amazonaws.com/NewProject.png?uploadId=nlWLdbNgB9zgarpLBXnj17eOIGAmQM_xyBArymtwdM71fhbFvveggDmL6fz4blz.B95TLhMatDvodbMb5p2ZMKqdlLeLFoSW1qcu33aRQTlt6NbiP_dkDO90DFO.pWGH"; AWS HTTP error: Client error: `POST https://bucket-name.s3.amazonaws.com/NewProject.png?uploadId=nlWLdbNgB9zgarpLBXnj17eOIGAmQM_xyBArymtwdM71fhbFvveggDmL6fz4blz.B95TLhMatDvodbMb5p2ZMKqdlLeLFoSW1qcu33aRQTlt6NbiP_dkDO90DFO.pWGH` resulted in a `400 Bad Request` response:
<Error><Code>InvalidPart</Code><Message>One or more of the specified parts could not be found. The part may not have be (truncated...)
InvalidPart (client): One or more of the specified parts could not be found. The part may not have been uploaded, or the specified entity tag may not match the part's entity tag. - <Error><Code>InvalidPart</Code><Message>One or more of the specified parts could not be found. The part may not have been uploaded, or the specified entity tag may not match the part's en"
I think that the problem is I've tried translating the JS found here to PHP, but although it's returning a URL, it's not correct. The notable difference is that I'm not passing an "UploadId" or a "PartNumber".
I've scoured the AWS docs, Google, Stackoverflow, Ask Jeeves, etc and couldn't find a PHP equivalent of the "getSignedUrl" method
public function signPartUpload(Request $request, $uploadId, $partNumber)
{
$client = new S3Client([
'version' => 'latest',
'region' => 'us-east-1',
]);
$key = $request->has('key') ? $request->get('key') : null;
if (!is_string($key)) {
return response()->json(['error' => 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"'], 400);
}
if (!intval($partNumber)) {
return response()->json(['error' => 's3: the part number must be a number between 1 and 10000.'], 400);
}
//Creating a presigned URL
$cmd = $client->getCommand('PutObject', [
'Bucket' => 'bucket-name',
'Key' => $key
]);
$response = $client->createPresignedRequest($cmd, '+20 minutes');
$presignedUrl = (string)$response->getUri();
return response()->json(['url' => $presignedUrl]);
}
Any help would be greatly appreciated!
I found the PHP equivalent of the getSignedUrl method.
$command = $this->client->getCommand('UploadPart', [
'Bucket' => $this->bucket,
'Key' => $key,
'PartNumber' => $partNumber,
'UploadId' => $uploadId,
'Body' => '',
]);
Here's my solution:
/**
* Create a pre-signed URL for parts to be uploaded to.
* #param Request $request
* #param string $uploadId
* #param int $partNumber
* #return JsonResponse
*/
public function signPartUpload(Request $request, string $uploadId, int $partNumber)
{
$key = $request->has('key') ? $request->get('key') : null;
// Check key
if (! is_string($key)) {
return response()->json(['error' => 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"'], 400);
}
// Check part number
if (! intval($partNumber)) {
return response()->json(['error' => 's3: the part number must be a number between 1 and 10000.'], 400);
}
// Create the upload part command and get the pre-signed URL
try {
$command = $this->client->getCommand('UploadPart', [
'Bucket' => $this->bucket,
'Key' => $key,
'PartNumber' => $partNumber,
'UploadId' => $uploadId,
'Body' => '',
]);
$presignedUrl = $this->client->createPresignedRequest($command, '+20 minutes');
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
// Convert the pre-signed URL to a string
$presignedUrlString = (string) $presignedUrl->getUri();
return response()->json(['url' => $presignedUrlString]);
}
Related
latestAll S3 bucket file is displayed, but when I upload file then error is generate.
I have ARN and instance profile.
use Aws\Credentials\CredentialProvider;
use Aws\Credentials\InstanceProfileProvider;
use Aws\Credentials\AssumeRoleCredentialProvider;
use Aws\S3\S3Client;
use Aws\Sts\StsClient;
$profile = new InstanceProfileProvider();
$ARN = ""; // MY ARN
$sessionName = "s3-access-example";
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient([
'region' => "ap-east-1",
'version' => "latest",
'credentials' => $profile
]),
'assume_role_params' => [
'RoleArn' => $ARN,
'RoleSessionName' => $sessionName,
],
]);
$provider = CredentialProvider::memoize($assumeRoleCredentials);
$this->s3hd = S3Client::factory([
'credentials' => $provider,
'version' => "latest",
'region' => "ap-east-1"
]);
public function upload($name, $file, $type, $Bucket = false)
{
if (! $Bucket) {
$Bucket = $this->bucket;
}
$result = $this->s3hd->putObject([
'Bucket' => $Bucket,
'Key' => $name,
'SourceFile' => $file,
'ContentType' => $type,
'ACL' => 'public-read'
]);
$this->s3hd->waitUntil('ObjectExists', [
'Bucket' => $Bucket,
'Key' => $name
]);
return $result;
}
Message: Error executing "PutObject" on error file url here; AWS HTTP error: Client error: PUT error file url here resulted in a 400 Bad Request` response: InvalidTokenThe provided token is malformed or other (truncated...) InvalidToken (client): The provided token is malformed or otherwise invalid. - InvalidTokenThe provided token is malformed or otherwise invalid.
In my case. I was trying through CLI.
I configured AWS cli by running
aws configure
Inside ~/.aws/credentials, look for session_token. If you have the session_token. Then update it.
Otherwise remove session_token and try again.
And Voila It worked!
You're getting this error because Hong Kong (ap-east-1) is not enabled by default. You need to enable it in the AWS console if you have the correct permissions, then try again.
See the AWS Docs for instructions on how to do that.
I am using s3cmd and based on the above answer I was able to solve by deleting the .s3cmd file and reconfiguring (s3cmd --configure), which cleared the access_token:
diff .s3cfg previous_s3cmd
< access_token =
---
> access_token = vkp1Jf\etc...
Also increased the chunk sizes:
< recv_chunk = 65536
---
> recv_chunk = 4096
< send_chunk = 65536
---
> send_chunk = 4096
And I guess I had previously opted for https requests, as opposed to the (current) default:
< use_https = True
---
> use_https = False
Success
Success. Your access key and secret key worked fine :-)
Now verifying that encryption works...
Success. Encryption and decryption worked fine :-)
I'm getting this error even if I already provided a MessageGroupId parameter:
AWS HTTP error: Client error: POST https://sqs.us-west-2.amazonaws.com/xxx/xxx.fifo resulted in a 400 Bad Request response: SenderM (truncated...) MissingParameter (client): The request must contain the parameter MessageGroupId. - SenderMissingParameterThe request must contain the parameter MessageGroupId ...
Here's a sample code:
$client = new Aws\Sqs\SqsClient([
'region' => 'us-west-2',
'version' => '2012-11-05',
'MessageGroupId' => 'testGroup',
'credentials' => [
'key' => 'xxx',
'secret' => 'xxx'
]
]);
$params = [
'MessageBody' => 'foo',
'QueueUrl' => 'https://sqs.us-west-2.amazonaws.com/xxx/xxx.fifo'
];
try {
$result = $client->sendMessage($params);
var_dump($result);
} catch (Aws\Exception\AwsException $e) {
echo $e->getMessage();
}
Don't know why I put MessageGroupId in the SqsClient() parameter when it should've been in the sendMessage() $params array.
I'm currently struggling with getting a S3 download link working. I've been using this code as reference but when I try to open the file, I get the error:
The authorization mechanism you have provided is not supported. Please
use AWS4-HMAC-SHA256.
I tried a few other scripts floating around, but all ended with some other error message.
Is there an easy way to migrate the script I'm using to make it work with Signature v4?
UPDATE: as suggested by hjpotter92, I used the AWS-SDK and came up with this working code:
$client = S3Client::factory([
'version' => 'latest',
'region' => 'eu-central-1',
'signature' => 'v4',
'credentials' => [
'key' => '12345',
'secret' => 'ABCDE'
]
]);
$cmd = $client->getCommand('GetObject', [
'Bucket' => '###name###',
'Key' => $fileName
]);
$request = $client->createPresignedRequest($cmd, '+2 minutes');
$presignedUrl = (string) $request->getUri();
return $presignedUrl;
$accessKey = 'XZA...';
$accessSecret = 'YKW...';
$credentials = new Aws\Credentials\Credentials($accessKey, $accessSecret);
$sharedConfig = [
'region' => 'us-east-1',
'version' => 'latest',
'credentials' => $credentials
];
$sdk = new Aws\Sdk($sharedConfig);
$sns = new SnsClient($sharedConfig);
$payload = [
'PhoneNumber' => '+999999999', // E.164 format
'Message' => md5(time()),
'MessageAttributes' => [
'DefaultSenderID' => ['DataType'=>'String','StringValue'=>'MyBrandName'],
'DefaultSMSType' => ['DataType'=>'String','StringValue'=>'Transactional']
]
];
try {
$data = $sns->publish( $payload );
$MessageId = $data->get('MessageId');
} catch ( Exception $e ) { }
I'm using the AWS SDK for PHP - Version 3.
The code above works well when i'm sending a single SMS message except the attribute DefaultSenderID wich is not working when i send a SMS to a mobile device.
Amazon documentation says that DefaultSenderID – A string, such as your business brand, that is displayed as the sender on the receiving device. Support for sender IDs varies by country. The sender ID can be 1 - 11 alphanumeric characters, and it must contain at least one letter.
Anyone has experienced this problem using the Amazon SNS?
For anybody still struggling with this.
If you look at the documentation here, you will find that you need to add the key AWS.SNS.SMS.SenderID to the payload's MessageAttributes.
The following should work:
$payload = [
'PhoneNumber' => '+999999999', // E.164 format
'Message' => md5(time()),
'MessageAttributes' => [
'AWS.SNS.SMS.SenderID' => [
'DataType' => 'String',
'StringValue' => 'YourSenderID',
]
]
];
try {
$data = $sns->publish($payload);
$MessageId = $data->get('MessageId');
} catch (Exception $e) { }
Im uploading some images to S3, how can I check if it was a successful transfer?
Here is my code. I screw up the access key on purpose so the files do not upload, how can I catch this error and act upon it?
The code below does not catch anything, even though the images fail to upload.
$this->commands[] = $this->s3->getCommand('PutObject', [
'Bucket' => env('AWS_BUCKET'),
'Key' => $name,
'Body' => $img,
'ContentType' => $mime,
'ACL' => 'public-read'
]);
$pool = new CommandPool($this->s3, $this->commands);
$promise = $pool->promise();
try {
$result = $promise->wait();
}
catch (AwsException $e) {
var_dump($e)
}
Im using php sdk 3.0
I am also using PHP SDK 3.0 and was able to get the result of the upload using the following:
$result = $s3Client->putObject(array(
'Bucket' => $bucketName,
'Key' => $backupFileName,
'SourceFile' => $backupFile,
));
$code = $result['#metadata']['statusCode'];
$uri = $result['#metadata']['effectiveUri'];
if ($code === 200) {
// Success code here
}