I have a signedURL for a google cloud storage bucket, and I want to use it with axios to make a PUT request.
My putFileData function is called when the variable signedURL is not empty, via useEffect.
const putFileData = async () => {
await axios
.put(signedURL, "HELLO TXT!!!!")
.then((response) => console.log(response))
.catch(err => {console.log("AXIOS ERROR: ", err)})
}
I set the CORS policy on the bucket with a json file, and when I query the bucket's cors policy I get:
[{"maxAgeSeconds": 360, "method": ["PUT"], "origin": ["http://localhost:3000"], "responseHeader": ["Content-Type"]}]
The options on my signedURL are:
const options = {
version: 'v4',
action: 'write',
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
contentType: 'application/octet-stream',
};
Yet I still can't do the PUT request from http://localhost:3000.
I get:
Access to XMLHttpRequest at 'mysignedurl' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
and:
PUT mysignedurl::ERR_FAILED
In my Network tab of Chrome Developer tools it shows the request is made twice - first unsuccessfully with status 403, then successfully with status 200 - yet nothing is uploaded to the bucket.
My signed url is generated with this function in my Cloud Functions:
async function generateV4UploadSignedUrl(bucketName, fileName) {
// These options will allow temporary uploading of the file with outgoing
// Content-Type: application/octet-stream header.
const options = {
version: 'v4',
action: 'write',
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
contentType: 'application/octet-stream',
};
// Get a v4 signed URL for uploading file
const [url] = await storage
.bucket(bucketName)
.file(fileName)
.getSignedUrl(options)
return url;
};
With the help of the Google Cloud Support team, I figured out the ContentType was incorrect. I changed the options to:
and it worked!