You need to format it by adding ``` on the line just before it and just after it :)
Jan 19, 2022
7
Level 1
AWS S3 Presigned Url Error SignatureDoesNotMatch
I use Laravel as an API and it creates a presigned URL for AWS S3. Then i use this generated URL to upload a image directly from my Vue.js frontend. But this does not work. I get Error 403-SignatureDoesNotMatch.
Full Error: The request signature we calculated does not match the signature you provided. Check your key and signing method.
Laravel function:
public function getSecureUrl(Request $request) {
try {
$url = Storage::temporaryUrl(
'test.jpg', now()->addMinutes(60)
);
return response([
'secure-url' => $url
]);
} catch(\Exception $exception) {
return response([
'message' => $exception->getMessage()
], 400);
}
}
Vue.js function which gets the presigned url from Laravel
submitFile() {
const formData = new FormData();
formData.append('file', this.Images);
const headers = { 'Content-Type': 'multipart/form-data' };
axios.put('https://test-bucket-cvolk.s3.eu-central-1.amazonaws.com/test.jpg?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT6ILWME6MFPK2YYP%2F20220119%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20220119T182421Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=d05df7544080dbd9a6b71fbc5351bde1b3230e94439236621b64a4d7b2505477', formData, { headers }).then((res) => {
res.data.files; // binary representation of the file
res.status; // HTTP status
});
}
The URL in the axios method is what i get from Laravel.
What am i doing wrong here?
Level 1
Found a new approach which works perfectly....
Please let me know if something can be written more elegant =)
Laravel:
public function generatePresignedPostUrl(Request $request) {
$this->validate($request, [
'filename' => 'string|required'
]);
$s3 = Storage::disk('s3');
$client = $s3->getDriver()->getAdapter()->getClient();
$expiry = "+10 minutes";
$cmd = $client->getCommand('PutObject', [
'Bucket' => env('AWS_BUCKET'),
'Key' => 'images/' . $request->filename
]);
$request = $client->createPresignedRequest($cmd, $expiry);
$presignedUrl = (string)$request->getUri();
return response()->json(['url' => $presignedUrl], 201);
}
Vue.js:
async uploadImage(e) {
if (!e.target.files[0]) return;
try {
let imageFile = e.target.files[0];
let fileName = imageFile.name;
let formData = new FormData();
formData.set("filename", fileName);
let res = await axios.post("/generate-presigned-post-url",formData);
formData.append("file", imageFile);
try {
await axios.put(res.data.url, formData);
} catch(err) {
console.log("Failed to upload");
console.log(err);
}
} catch(err) {
console.log("Failed to upload");
console.log(err);
}
}
Please or to participate in this conversation.