I am trying to build an app that uploads an image to AWS S3 using React frontend and Node / Express backend.
When the "upload" button is clicked, I want my app to
- Get secret upload URL from express backend
- Upload image to that secret upload URL.
So Far, I made to the point where react can fetch GET request to my backend & my backend can get such requests. However, for some reason the log says "Fetch failed loading GET" and is unavailable to get response from the fetch request.
I also tried using useState and useEffect, but I can't seem to resolve the issue.
React file Upload.js
import 'bootstrap/dist/css/bootstrap.css';
import React, {useState} from 'react';
function Upload() {
const [selectedFile, setSelectedFile] = useState(null);
const handleFileInput = (e) => {
setSelectedFile(e.target.files[0]);
console.log(e.target.files[0].name);
}
async function uploadFile(file) {
// code crashes here; fetch request does successfully reach backend, but it fails to retrieve result.
const { url } = await fetch("/s3Url", {
headers:{
"accepts": "application/json"
}
}).then(res => res.json());
console.log(url)
await fetch(url, {
method: "POST",
headers: {
"Content-Type": "multipart/form-data"
},
body: file
})
.then(res => res.json())
}
return (
<div className="container">
<div className="row">
<form>
<h3>File upload to S3</h3>
<div className="form-group">
<input type="file" onChange={handleFileInput}/>
</div>
<div className="form-group">
<button className="btn btn-primary" type="submit" onClick={() => uploadFile(selectedFile)}>Upload</button>
</div>
</form>
</div>
</div>
)
}
export default Upload;
Backend server.js
import express from 'express';
import { generateUploadURL } from './s3.js';
const app = express();
app.use(express.json());
app.get('/s3Url', async (req, res) =>{
// this log works
console.log("request made")
const url = await generateUploadURL()
// this log works too
console.log(url)
res.send({url})
})
app.listen(8080, () => console.log("listening on port 8080"))
where generateUploadURL() is:
export async function generateUploadURL() {
const rawBytes = await randomBytes(16)
const imageName = rawBytes.toString('hex')
const params = ({
Bucket: bucketName,
Key: imageName,
Expires: 60
})
const uploadURL = await s3.getSignedUrlPromise('putObject', params)
return uploadURL
}