Using a Flask API on a ReactJs website, I have 2 routes on my server.py file.
On the frontend I can upload a file to firebase storage. In server.py, I have a route that uses POSTed information about the filename after it's uploaded, then downloads it from firebase.
# File download Link
@app.route('/filePath', methods=['POST'])
def get_path():
data = request.get_json()["path"]
storage.child(f"files/{data}").download(f"files/Resume.pdf")
return "Success.."
Then I have another route that does some logic with the file after it's been downloaded. The route then feeds the information to the frontend as such
# Details API Get Route
@app.route("/details")
def details():
path = r"path\to\pdf"
person_data = PersonAnalyser(path).get_data()
return {"email":person_data.get('email'),
"mobile_number":person_data.get('mobile_number'),
"name":person_data.get('name'),
}
My issue, is that the /details route is executed everytime the page loads up, before I can even upload a file. I'm not sure how I can change that.
Here's how I'm calling it on the frontend
const FileUpload = () => {
const [initialData, setInitialData] = useState([{}])
const [progress, setProgress] = useState(0);
const formHandler = (e) => {
e.preventDefault();
const file = e.target.files[0];
uploadFiles(file);
update();
};
const update = () => {
axios.get('http://localhost:3000/details').then((res) => {
setInitialData(res.data);
});
};
useEffect(update, []);
I'm not sure if the rest is relevant or not so I'll just post it, This is the entire FileUpload which I'm exporting and calling in App.jsx
const FileUpload = () => {
const [initialData, setInitialData] = useState([{}])
const [progress, setProgress] = useState(0);
const formHandler = (e) => {
e.preventDefault();
const file = e.target.files[0];
uploadFiles(file);
update();
};
const update = () => {
axios.get('http://localhost:3000/details').then((res) => {
setInitialData(res.data);
});
};
useEffect(update, []);
const uploadFiles = (file) => {
//
if (!file) return;
if (!initialData) return null;
const storageRef = ref(storage, `files/${file.name}`);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on(
"state_changed",
(snapshot) => {
const prog = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
setProgress(prog);
},
(error) => console.log(error),
() => {
getDownloadURL(uploadTask.snapshot.ref).then(() => {
axios.post('http://localhost:3000/filePath', {
'path': file.name
}).then(() => console.log(file.name));
});
}
);
};
return (
<>
<div className="file-card">
<div className="file-inputs">
<input type="file" onChange={formHandler} />
<button>
<i>
<FontAwesomeIcon icon={faPlus} />
</i>
Upload
</button>
</div>
<ProgressBar color={"#ff7979"} width={"150px"} value={Math.round(progress)} max={100} />
<p className="main">Supported files</p>
<p className="info">PDF, JPG, PNG</p>
</div>
<div>
<h3>Hello {initialData.name}</h3>
</div>
</>
)
}
export default FileUpload
Just to re-iterate, my problem is that /details
is executed when the page loads which throws off the entire workflow. It needs to wait for /filePath
to be called and finish executing to then start executing /details
. Any suggestions please?
CodePudding user response:
The below line is causing update()
to run on page load. If you don't want that then remove it:
useEffect(update, []);
To run it on /filePath
complete, then I'd suggest the .then()
for that axios call:
axios.post('http://localhost:3000/filePath', {
'path': file.name
}).then(() => {
console.log(file.name);
update();
});
In the formHandler
, you are immediately calling update()
after uploadFiles()
:
const formHandler = (e) => {
...
uploadFiles(file);
update();
};
This is a problem because uploadFiles()
is async, meaning update()
will run before uploadFiles()
completes. If you move update()
to the .then()
as suggested above, then you can remove it from formHandler
.