I just learning react and I create an gallery App, but I have problem with posting picture to API. The problem is that when I click on button ADD there's nothing happend just in console.log I get an error 500.
Here is my component with post request:
class AddPhoto extends Component {
constructor(props) {
super(props);
this.state = {
modal: false,
images: [],
isLoading: false,
error: null,
};
this.toggle = this.toggle.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
toggle() {
this.setState({
modal: !this.state.modal
});
}
handleClick(event) {
event.preventDefault();
this.setState({
modal: !this.state.modal
});
}
handleSubmit(event){
event.preventDefault();
this.setState({ isLoading: true });
let path = this.props.path;
fetch(`http://.../gallery/${path}`, {
method: 'POST',
headers: {'Content-Type':'multipart/form-data'},
body: new FormData(document.getElementById('addPhoto'))
})
.then((response) => response.json())
.then((data)=>{
this.setState({images: data.images, isLoading: false});
this.props.updateImages(data.images);
})
.catch(error => this.setState({ error, isLoading: false}));
}
render() {
return (
<Card className="add">
<div className="link" onClick={this.toggle}>
<CardBody>
<CardTitle>Add picture</CardTitle>
</CardBody>
</div>
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<div className="modal-header">
...
</div>
<ModalBody>
<form className="addPhotoForm" id="addPhoto" onSubmit={this.handleSubmit}>
<input type="file" required />
<Button color="success" type="Submit">Add</Button>
</form>
</ModalBody>
</Modal>
</Card>
);
}
}
Do you have any idea what am I doing wrong, why is not working, why I get error 500?
Thanks for helping me.
according to this https://muffinman.io/uploading-files-using-fetch-multipart-form-data it works in different way, at least for me it works as well.
const fileInput = document.querySelector('#your-file-input') ;
const formData = new FormData();
formData.append('file', fileInput.files[0]);
const options = {
method: 'POST',
body: formData,
// If you add this, upload won't work
// headers: {
// 'Content-Type': 'multipart/form-data',
// }
};
fetch('your-upload-url', options);
You should remove the 'Content-Type': 'multipart/form-data' and it started to work.
This is part of my upload component.
Look how i do it, you can modify it, with upload button, if you need.
addFile(event) {
var formData = new FormData();
formData.append("file", event.target.files[0]);
formData.append('name', 'some value user types');
formData.append('description', 'some value user types');
console.log(event.target.files[0]);
fetch(`http://.../gallery/${path}`, {
method: 'POST',
headers: {'Content-Type': 'multipart/form-data'},
body: {event.target.files[0]}
})
.then((response) => response.json())
.then((data) => {
this.setState({images: data.images, isLoading: false});
this.props.updateImages(data.images);
})
.catch(error => this.setState({error, isLoading: false}));
}
render() {
return (
<div>
<form encType="multipart/form-data" action="">
<input id="id-for-upload-file" onChange={this.addFile.bind(this)} type="file"/>
</form>
</div>)
}
This worked fine for me, just try it:
var myHeaders = new Headers();
myHeaders.append("Accept", "application/json");
myHeaders.append("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJh");
var formdata = new FormData();
formdata.append("image", fileInput.files[0], "Your_iamge_URL");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow'
};
fetch("YOUR_API_ToCall", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
If you need to send a request with more attributes than the image use:
document.getElementById('inputPhoto').addEventListener('change', (e) => {
let data = new FormData();
const image = e.target.files[0];
data.append('id', 'sendIDHere');
data.append('name', 'sendNameHere');
data.append('image', image);
fetch('/apiToReceiveImage', {
method: 'POST',
body: data
}).then(async (_res) => {
const result = await _res.json();
console.log(result);
});
});
Remember that all attributes should be appended BEFORE the image
Related
I have to update an object in an array when I click on the button. But I can't select the object I clicked.
there is my git for better reading https://github.com/Azciop/BernamontSteven_P7_V2
Code:
data() {
return {
post: {
file: "",
content: "",
},
showModal: false,
showModifyPost: false,
user: {
firstname: "",
lastname: "",
_id: "",
},
};
},
this is the get function
getAllPost() {
axios
.get('http://127.0.0.1:3000/api/post')
.then((response) => {
console.log("getPosts", response.data);
this.post = response.data;
}).catch(error => {
console.log(error);
})
},
this is the update post function
updatePost(id) {
const formData = new FormData();
formData.append("image", this.post[1].file);
formData.append("content", this.post[1].content);
axios.put('http://127.0.0.1:3000/api/post/' + id, formData,
{
headers: {
Authorization: "Bearer " + localStorage.getItem("token"),
'Content-Type': 'application/json',
},
})
.then(response => {
console.log(response);
location.reload("/accueil");
}).catch(e => {
console.log(e);
}
)
},
and this is the html with the v-for to display and the modify part
<div class="post" :key="post._id" v-for="post in post">
<!-- update a post -->
<button #click="showModifyPost = true" v-if="post.userId == user._id || user.isAdmin == true"
class="button button-modify-post">Modifier</button>
<transition name="fade" appear>
<div class="modal-overlay" v-if="showModifyPost" #click="showModifyPost = false"></div>
</transition>
<transition name="slide" appear>
<div class="modifiyPostModal" v-if="showModifyPost">
<span>
<h2 class="center-text">Modifier votre publication</h2>
<div class="close-post_button" #click="showModifyPost = false">
<font-awesome-icon class="close_create_post" icon="fa-solid fa-circle-xmark" />
</div>
</span>
<form enctype="multipart/form-data">
<div>
<input class="textPost" name="createPost" placeholder="Quoi de neuf ?"
v-model="post.content" />
</div>
<div class="center-sendbutton">
<input type="file" class="publishPost" id="changePicture" v-on:change="selectFile" ref="file" />
<button type="submit" v-on:click.prevent="updatePost(post._id)" class="publishPost">Modifier</button>
</div>
</form>
</div>
</transition>
This is the create Function
selectFile() {
this.posts.file = this.$refs.file.files[0];
},
// create post
async submitCreatePost() {
const formData = new FormData();
formData.append('image', this.posts.file);
formData.append('content', this.posts.content);
formData.append('firstname', localStorage.getItem("firstname"));
formData.append('lastname', localStorage.getItem("lastname"));
formData.append('userId', localStorage.getItem("userId"));
await axios.post("http://127.0.0.1:3000/api/post",
formData,
{
headers: {
Authorization: "Bearer " + localStorage.getItem("token"),
}
}).then(
console.log(formData),
this.content = "",
this.file = "",
).then((response) => response.status >= 200 || response.status <= 201 ?
location.reload(true) : console.log(response.statusText))
.catch(error => console.log(error));
},
but when i update it, it does update the object 1 (because it's the one selected in the js function)
i'd like to know how can i do to select the object i clicked. Thanks
Can you try this
export default {
created(){
this.getAllPost()
},
data(){
return{
posts: [],
post: {
file: "",
content: "",
},
showModal: false,
showModifyPost: false,
user: {
firstname: "",
lastname: "",
_id: "",
},
}
},
methods:{
getAllPost() {
axios
.get('http://127.0.0.1:3000/api/post')
.then((response) => {
console.log("getPosts", response.data);
this.posts = response.data;
}).catch(error => {
console.log(error);
})
},
updatePost(id) {
//the find part
const postToBeFound=this.posts.find((post)=>post._id===id)
console.log(postToBeFound)
const formData = new FormData();
formData.append("image", postToBeFound.file);
formData.append("content", postToBeFound.content);
axios.put('http://127.0.0.1:3000/api/post/' + id, formData,
{
headers: {
Authorization: "Bearer " + localStorage.getItem("token"),
'Content-Type': 'application/json',
},
})
.then(response => {
console.log(response);
location.reload("/accueil");
}).catch(e => {
console.log(e);
}
)
}
}
}
Error is happening at
formData.append("image", this.post[1].file);
formData.append("content", this.post[1].content);
since post is an object post[1] will give error. In my original answer also I made the fix
formData.append("image", postToBeFound.file);
formData.append("content", postToBeFound.content);
found a way to do it, don't know if it the right way but it works so...
when i click on the modify button i store the current post's id in the local storage and then i do this.
updatePost() {
const thisPostId = localStorage.getItem("ThisPostId")
let formData = new FormData();
formData.append("image", this.post.file);
formData.append("content", this.post.content);
axios.put('http://127.0.0.1:3000/api/post/' + thisPostId, formData,
{
headers: {
Authorization: "Bearer " + localStorage.getItem("token"),
"Content-Type": "multipart/form-data",
},
})
.then(response => {
this.posts = response.data;
this.getAllPost();
this.showModifyPost = false
}).catch(e => {
console.log(e);
}
)
},
SO I am calling 5 APIs in my js file and the code is the same for all except the URL and the form data I am passing. and same lines of code repeats 5 times and I think this is not the good of writing. What I want is to make this code dry but don't know what changes I should make
var formdata = new FormData();
formdata.append("market", "KSE100");
var requestOptions = {
method: "POST",
body: formdata,
redirect: "follow",
};
fetch(
"api_url here_1",
requestOptions
)
.then((response) => response.json())
.then((stockData) => console.log('aasfs',stockData ))
.catch((error) => console.log("error", error));
var formdata = new FormData();
formdata.append("symbol", "SYS");
var requestOptions = {
method: "POST",
body: formdata,
redirect: "follow",
};
fetch(
"api_url here_2",
requestOptions
)
.then((response) => response.json())
.then((stockData) => console.log('aasfs',stockData ))
.catch((error) => console.log("error", error));
Wrap the common code in a function passing in the form data and url via variables
const sendFormData = (url, formData) => {
var requestOptions = {
method: "POST",
body: formData,
redirect: "follow",
};
fetch(
url,
requestOptions
)
.then((response) => response.json())
.then((stockData) => console.log('aasfs', stockData))
.catch((error) => console.log("error", error));
}
var formdata1 = new FormData();
formdata.append("market", "KSE100");
sendFormData("api_url here_1", formdata1);
var formdata2 = new FormData();
formdata.append("symbol", "SYS");
sendFormData("api_url here_2", formdata2);
You can define a function like this
const postData = (url, data) => {
const formdata = new FormData();
Object.entries(data).forEach(([k, v]) => {
formdata.append(k, v);
}
var requestOptions = {
method: "POST",
body: formdata,
redirect: "follow",
};
return fetch(
url,
requestOptions
)
.then((response) => response.json())
.then((stockData) => console.log('aasfs',stockData ))
.catch((error) => console.log("error", error));
}
I am trying to login using PHP in react native so I am using fetch api but when I try to login it's always saying fields are blank whereas it's not. Can somebody help me with this?
Code:
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
Username: '',
Password: '',
}
}
login = () => {
const {
Username,
Password
} = this.state;
var payload = {
username: Username,
password: Password
};
this.state[payload];
var data = new FormData();
data.append("json", JSON.stringify(payload));
fetch("http://example.com/api.php", {
method: 'POST',
header: {
'Accept': 'application/json',
'Content-type': 'application/json'
},
body: data
})
.then(function(res) {
return res.json();
})
.then(function(data) {
alert(JSON.stringify(data))
})
.catch((error) => {
console.error(error);
});
}
}
Text input:
<TextInput
style={styles.input}
placeholder={'Username'}
placeholderTextColor={'#fff'}
underlineColorAndroid='transparent'
onChangeText={Username => this.setState({ Username })}
/>
<TextInput
style={styles.input}
placeholder={'Password'}
secureTextEntry={this.state.showPass}
placeholderTextColor={'#fff'}
underlineColorAndroid='transparent'
onChangeText={Password => this.setState({ Password })}
/>
If the name and password status value are not empty, try this.
let data = new FormData();
data.append("username", this.state.Username);
data.append("password", this.state.Password);
fetch("http://example.com/api.php",{
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
},
body: data
}).then((response) => response.json())
.then((res) => {
console.log(res);
}).catch(err => {
console.log(err)
})
});
OR
If you're trying to get him to JSON:
fetch("http://example.com/api.php",{
method: 'post',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.Username,
password: this.state.Password,
}),
}).then((response) => response.json())
.then((res) => {
console.log(res);
}).catch(err => {
console.log(err)
})
});
Since you are sending a request of type application/json, you should send the data directly as a JSON string:
var data = JSON.stringify(payload);
I load CSV data in the React.js front-end using FileReader:
import React, { Component } from 'react';
import { CsvToHtmlTable } from 'react-csv-to-table';
import ReactFileReader from 'react-file-reader';
import Button from '#material-ui/core/Button';
const sampleData = `
NUM,WAKE,SIBT,SOBT
1,M,2016-01-01 04:05:00,2016-01-01 14:10:00
2,M,2016-01-01 04:05:00,2016-01-01 14:10:00
3,M,2016-01-01 04:05:00,2016-01-01 14:10:00
`;
class CSVDataTable extends Component {
state={
csvData: sampleData
};
handleFiles = files => {
var reader = new FileReader();
reader.onload = (e) => {
// Use reader.result
this.setState({
csvData: reader.result
})
this.props.setCsvData(reader.result)
}
reader.readAsText(files[0]);
}
render() {
return <div>
<ReactFileReader
multipleFiles={false}
fileTypes={[".csv"]}
handleFiles={this.handleFiles}>
<Button
variant="contained"
color="primary"
>
Load data
</Button>
</ReactFileReader>
<CsvToHtmlTable
data={this.state.csvData || sampleData}
csvDelimiter=","
tableClassName="table table-striped table-hover"
/>
</div>
}
}
export default CSVDataTable;
Then I should send csvData to the backend. What is a proper way to do it?
I tried to send csvData, but then it cannot be properly parsed in the backend. I assume that \n is incorrectly encoded, when csvData arrives to the backend:
fetchData = () => {
const url = "http://localhost:8000/predict?"+
'&wake='+this.state.wake+
'&csvData='+JSON.stringify(this.state.csvData);
fetch(url, {
method: "POST",
dataType: "JSON",
headers: {
"Content-Type": "application/json; charset=utf-8",
}
})
.then((resp) => {
return resp.json()
})
.then((data) => {
this.updateDelay(data.prediction)
})
.catch((error) => {
console.log(error, "catch the hoop")
})
};
How do you suggest me to send csvData? It looks like JSON.stringify(this.state.csvData) does something wrong. Please help me solving this issue. Thanks.
Update:
I tried this:
fetchData = () => {
fetch("http://localhost:8000/predict", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
wake: this.state.wake,
csvData: this.state.csvData
})
})
.then((resp) => {
return resp.json()
})
.then((data) => {
this.updateDelay(data.prediction)
})
.catch((error) => {
console.log(error, "catch the hoop")
})
};
But then I cannot receive data in Django backend (Python):
print(request.POST)
Output:
<QueryDict: {}>
or:
print(request.POST['csvData'])
Output:
django.utils.datastructures.MultiValueDictKeyError: 'csvData'
Or:
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
content = body['csvData']
print("content",content)
Output:
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char
0)
in your edit you are setting the content-type to application/json but sending a string in it.
body: JSON.stringify({
wake: this.state.wake,
csvData: this.state.csvData
})
Try changing this to
body: {
wake: this.state.wake,
csvData: this.state.csvData
}
I'm trying to use react-dropzone in my code and making a POST request to the server with axios, but the POST request always fails and I keep getting the following error:
Uncaught (in promise) Error: Request failed with status code 500
This is my component
constructor(props) {
super(props);
this.state = {
accepted: [],
};
['handleChange', 'handleValidSubmit'].forEach(v => {
this[v] = this[v].bind(this);
});
}
handleValidSubmit(event, values) {
const data = {
accepted: this.state.accepted,
};
console.log(data);
axios({
method: 'post',
url:
'https://oc6tq8iop5.execute-api.ap-southeast-1.amazonaws.com/dev/upload',
data: JSON.stringify(data),
}).then(data => {
console.log(data);
onDrop: accepted => {
accepted.forEach(file => {
req.attach(file.name, file);
});
req.end(callback);
var formData = new FormData();
formData.append('gambar', values.accepted);
console.log(formData);
};
});
}
handleChange(event) {
const { target } = event;
const value = target.type === 'checkbox' ? target.checked : target.value;
const { name } = target;
this.setState({
[name]: value,
});
}
And this is my render methods
<div className="dropzone">
<Dropzone
accept="image/jpeg, image/png, image/jpg"
onDrop={accepted => {
this.setState({ accepted });
}}
maxSize={200000}
multiple={false}
>
<p>Maksimal 2 MB (JPG/PNG)</p>
</Dropzone>
{this.state.accepted.map(f => (
<span key={f.name}>
{f.name} - {f.size} bytes
</span>
))}
</div>
You just need to send header with axios,
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
let fd = new FormData();
values.map((file) => {
fd.append('File[]',file);
});
axios.post(`${ROOT_URL}/ImageUpload`, fd, config)
.then((response) => {
callback(response);
})
.catch(error => {
errorResponse(error);
})