Upload a file from react to flask is not working - reactjs

I'm trying to upload a video from react to flask but when I make a POST request it gives me this error
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'file'
here is the backend:
#app.route("/releaseVideo",methods=["POST"])
def release():
request_data = request.files.get["file"]
print(request_data)
try:
request_data.save(os.path.join(app.config['UPLOAD_FOLDER'],'first video'))
except Exception:
print('COULD NOT')
return {"msg":"What am I DOING"},200
if __name__ == '__main__':
app.run(debug=True)
Here is the front end...I'm using axios instead of fetch because I heard that axios is better for file uploads than fetch .
const upload_file = (event) => {
event.preventDefault()
let file = document.querySelector('input[type="file"]')
const formdata = new FormData()
formdata.append("file",file);
axios("/releaseVideo", {
method:'POST',
body:formdata
})
.then(res => console.log(res))
.catch(err => console.warn(err));
}
return (
<>
<form onSubmit={upload_file}>
<label>Title: </label><br />
<input type="text" onChange={onTitleChange} value={title}/><br />
<label>Description:</label><br />
<textarea value={textArea} onChange={onTextAreaChange}></textarea>
<input type="file" id="file"/>
<input type="submit" value="Upload Video!" />
</form>
</>
)
So how can I get the video from the front end in a proper way?

Related

"Failed to load resource: the server responded with a status of 415 (Unsupported Media Type)". How to fix Error

I'm trying to submit post form data to an my api using react and I'm passing through JSON data like so.
`
function AddSong() {
const [title, setTitle] = useState("");
const [artist, setArtist] = useState("");
const [release_date, setReleaseDate] = useState("");
const [album, setAlbum] = useState("");
const [genre, setGenre] = useState("");
let handleSubmit = async (e) => {
e.preventDefault();
try {
let res = await fetch("http://127.0.0.1:8000/api/music_library/?format=json", {
method: "POST",
body: JSON.stringify({
title: title,
artist: artist,
album: album,
release_date: release_date,
genre: genre,
}),
});
let resJson = await res.json();
if (res.status === 200) {
setTitle("");
setArtist("");
setReleaseDate("");
setAlbum("");
setGenre("");
}
} catch (err) {
console.log(err);
}
};
`
Here is my submit form.
`
return (
<div className="App">
<form onSubmit={handleSubmit}>
<input
type="text"
value={title}
placeholder="Title"
onChange={(e) => setTitle(e.target.value)}
/>
<input
type="text"
value={artist}
placeholder="Artist"
onChange={(e) => setArtist(e.target.value)}
/>
<input
type="text"
value={release_date}
placeholder="Year"
onChange={(e) => setReleaseDate(e.target.value)}
/>
<input
type="text"
value={album}
placeholder="Album"
onChange={(e) => setAlbum(e.target.value)}
/>
<input
type="text"
value={genre}
placeholder="Genre"
onChange={(e) => setGenre(e.target.value)}
/>
<button type="submit">Create</button>
</form>
</div>
);
}
export default AddSong;
`
When I click submit on the form, Chrome gives me an error saying "Failed to load resource: the server responded with a status of 415 (Unsupported Media Type)". I know it has something to do with the HandleSubmit function and the url im giving it. Im just not sure how to structure it correctly.
I tried going to the django api website and changing the get request url to JSON. I was expecting that accept the JSON data im passing through however it did not and instead gave me the same error I got when using the regular url.

image file isnt being read by react

I am using formData to send details to my backend but somehow my image path isn't being sent.
Post photo
<div className="form-group">
<label className="btn btn-block btn-success">
<input
onChange={handleChange("photo")}
ref={inputRef}
type="file"
name="photo"
accept="image"
placeholder="choose a file"
/>
</label>
</div>
this is the form i am using
Handle change and submit button
const onSubmit = (event) => {
event.preventDefault();
setValues({...values,error:"",loading:true});
createProduct(user._id,token,JSON.stringify(values))
.then(data=>{
if(data.error){
setValues({...values,error:data.error});
}else{
setValues({...values,
name:"",
description:"",
price:"",
photo:"",
stock:"",
createdProduct:data.name,
loading:false});
}
}).then(response=>{
})
.catch(err=>console.log(err));
//
};
const handleChange = name => event => {
const value=name==="photo"?event.target.files[0]:event.target.value;
formData.append(name,value)
setValues({...values,[name]:value});
//
};
And this is the api call to backend
export const createProduct=(userId,token,product)=>{
console.log(product)
return fetch(`${API}/product/create/${userId}`,{
method: "POST",
headers:{
Accept: "application/json",
Authorization: `Bearer ${token}`
},body:product
})
.then(response=>{
return response.json();
})
.catch(err=>console.log(err));
}
The api is working fine with postman , I am using formidable in backend. Some answers from stack made the path of the file have c:\fakepath and so m too confused what to do .
Thanks for help.

Unable to retrieve API data using axios

I'm trying to build a simple login using an API but keep facing errors
import React from "react";
import { useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
export default function Login() {
const navigate = useNavigate();
const [formData, setFormData] = useState({
uid: "",
password: "",
blocked: 0
});
const handleSubmit = (e) => {
e.preventDefault();
console.log(formData);
const data = JSON.stringify(formData);
console.log(data);
axios
.post("https://myphysio.digitaldarwin.in/api/login/", data)
.then(function (response) {
console.log(response);
console.log("Successfully Logged in ");
navigate("/success");
})
.catch(function (error) {
console.log(error);
});
};
return (
<form onSubmit={handleSubmit}>
<h3>Login</h3>
<div className="form-group">
<label>uid Name</label>
<input
name="uid"
className="form-control"
placeholder="Enter your uid Name"
value={formData.uid}
onChange={(e) => setFormData({ ...formData, uid: e.target.value })}
/>
</div>
<div className="form-group">
<label>Password</label>
<input
type="password"
name="password"
className="form-control"
placeholder="Enter password"
value={formData.password}
onChange={(e) =>
setFormData({ ...formData, password: e.target.value })
}
/>
</div>
<button type="submit" className="btn btn-primary btn-block">
Submit
</button>
</form>
);
}
The error I keep facing is
console log of error
POST https://myphysio.digitaldarwin.in/api/login/ 500 (Internal Server Error)
Error: Network Error
at createError (createError.js:16:1)
at XMLHttpRequest.handleError (xhr.js:117:1)
POST https://myphysio.digitaldarwin.in/api/login/ net::ERR_CONTENT_LENGTH_MISMATCH 500 (Internal Server Error)
All your errors come from the backend so I suggest you to post a question in the django section (I looked at the link and I was django framework so I assume that you use django). Maybe you don't want to stringify your formData (usually it's common to send a json in a post request).

Unable to send a photo from React Native to Cloudinary

I'm trying to upload images to Cloudinary from my React Native app, but I'm getting the "400 Bad Request" saying the image I'm sending is ""x-cld-error": "Unsupported source URL".
ImageUpload.js
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1
})
if (!result.cancelled) {
setImageSource(result.uri);
}
}
I'm currently using the ImagePicker from expo-image-picker. I'm taking the imageSource I've obtained from above and appending it to data before sending it to Cloudinary. The result.uri shows the URL of the picture from the iOS simulator.
CreatePost.js
const uploadFile = async () => {
const data = new FormData();
data.append('file', imageSource);
data.append('upload_preset', 'test_folder')
const res = await fetch('https://api.cloudinary.com/v1_1/{my_cloudinary}/image/upload', {
method: 'POST',
body: data,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
})
const file = await res.json()
setImage(file.secure_url)
setLargeImage(file.eager[0].secure_url)
}
When I console.log res, it shows that the status is 400.
You can try using ajax. For example here:
<h1>Upload to Cloudinary with FormData</h1>
<div>
<p>
Set your cloud name in the API URL in the code: "https://api.cloudinary.com/v1_1/<strong><cloud name></strong>/image/upload" before running the example.
</p>
</div>
<form action="" method="post" enctype="multipart/form-data" onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Upload example</legend>
<p>
<label for="upload_preset">Unsigned upload Preset: <input type="text" name="upload_preset">(set it here)</label>
</p>
<p>
<label >Select your photo:
<input type="file" name="file"></label>
</p>
<p>
<input type="submit" value="Submit" />
</p>
<img id="uploaded">
<div id="results"></div>
</fieldset>
</form>
enter code here https://jsfiddle.net/shirlymanor/s1hou7zr/

Issue to submit CSV file to DB via POST Axios & React-Final-Form

I need to save the content of a CSV into a database table by using React-Final-Form and Axios.
I have tried to create a simple HTML without using Final-Form or Axios and the submission to the DB works fine.
The problem is when I try to pass the content of the CSV to a function which will handle the POST call.
See code below:
import React, { Fragment } from "react";
import { Form, Field } from "react-final-form";
import createDecorators from "final-form-focus";
const handleSubmitOnClick = file => {
const url = 'http://localhost:3000/api/v1/invitations/upload';
const data = new FormData();
data.append('file', new File([file], { type: 'text/csv' }));
return axios.post(url, data, {
headers: {
'content-type': 'multipart/form-data'
}
})
.then(response => console.log(response))
.catch(error => console.log(error));
}
const JoinTesting = () =>
<Fragment>
<h1>Join Testing Page</h1>
<Form
onSubmit={handleSubmitOnClick}
decorators={[focusOnError]}
>
{
({
handleSubmit,
values,
submitting,
}) => (
<form onSubmit={handleSubmit} encType="multipart/form-data">
<Field
name='invitation[file]'
placeholder='Upload csv file'
validate={required}
>
{({ input, meta, placeholder }) => (
<div className={meta.active ? 'active' : ''}>
<label>{placeholder}</label>
<input {...input}
type='file'
placeholder={placeholder}
className="join-field-input"
/>
{meta.error && meta.touched && <span className="invalid">{meta.error}</span>}
{meta.valid && meta.dirty && <span className="valid">Great!</span>}
</div>
)}
</Field>
<button
type="submit"
className="join-button"
disabled={submitting}
>
Submit
</button>
<pre>{JSON.stringify(values, 0, 2)}</pre>
</form>
)}
</Form>
</Fragment>
export default JoinTesting;
If I remove ALL the above and I just use this HTML within my JoinTesting component, it works fine but I can't handle the errors (if any)
<form action="http://localhost:3000/api/v1/invitations/upload" method="post" encType="multipart/form-data">
Select CSV to upload:
<input type="file" name="invitation[file]" id="fileToUpload" />
<br></br>
<input type="submit" value="Upload CSV" name="submit" />
</form>
PLEASE NOTE: The CSV file has only a simple 1 column with a sequence of email addresses.
This is what the POST request expects:
Headers:
Content-Type: application/json
Accept: application/json
Body
{
"invitation": {
"file": "Email\nuser_1#gmail.com\nuser_2#gmail.com\nuser_3#gmail.com\nuser_4#gmail.com\n"
}
}
The API response expected for a success call is:
{
"success": true,
"emails": [
"user_1#gmail.com",
"user_2#gmail.com",
"user_3#gmail.com",
"user_4#gmail.com"
]
}
I hope someone can help.
George
If you're not using html form + HTTP POST + encType="multipart/form-data", then you'll need to handle the file upload yourself.
One way to do it: get reference to the input component, listen to changes, when a change happens get the filename from the input reference, read the file, save the data. Here's a component for that:
function FileInput(props) {
const fileInput = useRef(null);
const setRef = ref => {
fileInput.current = ref;
};
async function handleInputChange() {
const { files } = fileInput.current;
props.onChange(files[0]);
}
return (
<input
ref={setRef}
type="file"
placeholder={props.placeholder}
className="join-field-input"
onChange={handleInputChange}
/>
);
}
Use this within the Field component, and the form state will contain the file:
<Field name="invitation[file]" placeholder="Upload csv file">
{({ input, meta, placeholder }) => (
// ...
<FileInput {...input} placeholder={placeholder} />
// ...
)}
</Field>
Also the handleSubmitOnClick gets the whole values object. Your values should look something like this:
values = { invitation: { file: {} } }
So, change the handleSubmitOnClick function to:
const handleSubmitOnClick = values => {
const data = new FormData();
const { file } = values.invitation;
data.append('file', file, file.name);
// ...
}
Here's a codesandbox.

Resources