'Error in posting file to S3 via a pre-signed URL
I am building a vue app to upload files to s3. The app makes an API call with file details which will be stored in the database and the API call will return a pre-signed URL where the file will be saved. UI to API flow works, however, the axios PUT call to save the file in S3 fails.
Step 1: Call the API (SUCCESS) Step 2: Save the file details and return a pre-signed URL (SUCCESS) Step 3: upload the file via axios (or Postman) (FAIL)
The web code is:
var fileName = uuidv4() + ".webm";
var apiData = {
body: {
data: {
recordedBy: username,
fileName: fileName,
fileType: mediaType,
},
},
};
API.post(apiName, apiPath, apiData)
.then((response) => {
var url = response.url;
console.log("url: ", url);
// var options = { headers: { "Content-Type": mediaType } };
var file = new File([recording.blob], fileName);
axios
.put(url, file) //, options)
.then(function (response) {
console.log("axios put: ", response);
})
.catch(function (error) {
console.log("axios put error", error);
});
})
.catch((error) => {
console.log(error);
});
}
},
The server code is:
body = json.loads(event['body'])
recordingInformation = body["data"]
try:
s3Client = boto3.client('s3', config=Config(signature_version='s3v4'))
except Exception as e:
print("exception is:", e)
return {
'statusCode': 400,
'error': e
}
bucket = os.environ['STORAGE_BUCKETRECORDINGS_BUCKETNAME']
fileName = recordingInformation['fileName']
expiryTime = datetime.now() + timedelta(minutes=3)
action = 'put_object'
try:
URL = s3Client.generate_presigned_url(
action, Params={"Bucket": bucket, "Key": fileName, "Expires": expiryTime, "ContentType": recordingInformation['fileType']})
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
},
'body': json.dumps({'url': URL})
}
except Exception as e:
print("exception is: ", e)
return {
'statusCode': 400,
'error': e
}
The axios put gives the following error:
axios put error Error: Request failed with status code 403
at createError (createError.js?770c:16:1)
at settle (settle.js?8768:17:1)
at XMLHttpRequest.onloadend (xhr.js?1a5c:54:1)
If I try the same URL via postman with file in Body/Binary, I get the following error:
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
Any recommendations on what's off here?
Solution 1:[1]
After changing to generate_presigned_post, the client code looks like below:
var signed_url = response.url;
console.log("url: ", signed_url);
const formData = new FormData();
Object.keys(signed_url.fields).forEach((key) => {
formData.append(key, signed_url.fields[key]);
});
// Actual file has to be appended last.
// var options = { headers: { "Content-Type": mediaType } };
var file = new File([recording.blob], fileName);
formData.append("file", file);
axios
.post(signed_url.url, formData) //, options)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | VV75 |
