How can I update image using ReactJs and axios - reactjs

I have problem to update my image using react and axios I convert it in a form data but can’t work it always affiche an error in axios data
This is my method to put data when I remove image in the axios data the request go to the api with success when i put image in the axios data the request is unsuccessful ;(
onSubmit = (e) => {
e.preventDefault();
let fd = new FormData();
fd.append('image', this.state.images, this.state.images.name);
console.log(fd);
const { id, nom} = this.state.patient;
axios.put('/patients/' + this.props.match.params.id, {id, nom,fd})
.then((result) => {
this.props.history.push("/show/" + this.props.match.params.id)
if (result.data != null){
this.setState(this.initialState);
}
});
}
This is my handler image
handleFile(e) {
this.setState({ images: e.target.files[0] });
this.setState({ image: '' });
let reader = new FileReader();
let images = e.target.files[0];
reader.onloadend = () => {
this.setState({ file: images, imagePreviewUrl: reader.result });
}
reader.readAsDataURL(images)
}

Related

React FileReader readAsDataURL not working: URL can't be decoded in flask backend as format == None

I'm working on a basic React web app where user can upload images, and images are send to the flask backend to be processed. I'm using FileReader class to convert the uploaded images through into URLs, and then send them to the backend, where I need to decode the URLs then converted it into an np.array for the processing.
The issue is, when I try to decode the image with image_data = base64.b64decode(image_url) and get the image with Image.open(io.BytesIO(image_data)), somehow it won't recognize the url as an image? Basically I got this error:
raise UnidentifiedImageError(
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x2e8950b30>
I checked the image format with image_format = imghdr.what(io.BytesIO(image_data)), and the image_format equals to None. Do I need to specify the format when encoding the image?
Here's my code:
in React App():
handleImageUploadSelect = (event) => {
let imageURLs = [];
const files = event.target.files;
for ( let i = 0; i < files.length; i++ ) {
// load file object
const file = files[i]
// file reader
const reader = new FileReader();
reader.onload = (event) => {
const dataURL = event.target.result;
// add dataURL to the state variable
imageURLs[i] = dataURL;
}
reader.readAsDataURL(file);
}
this.state.uploadImageURLs = imageURLs;
}
handleImageUpload = event => {
event.preventDefault();
// send uploadImageURLs back to flask server
const data = { images: this.state.uploadImageURLs };
console.log(data)
fetch('http://127.0.0.1:5000/add_images', {
method:'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
},
})
.then((response) => response.json())
.then((data) => {
// response data
console.log(data)
})
.catch((error) => {
console.error(error);
});
}
And in flask server file:
#main.route('/add_images', methods=['POST'])
#cross_origin()
def add_images():
data = request.get_json()
for imageURL in data['images']:
image_data = base64.b64decode(imageURL)
image = Image.open(io.BytesIO(image_data))
image_array = np.array(image)
# processing ...
return jsonify({"condition": "image received"})
Please Help! Thanks!

react-mic record audio and send the blob as mp3/wav to backend

Basically I want to record audio and I'm using react-mic for this but it gives back blob but I want mp3 or wav file to send to the backend. How to POST blob file to the server?
This is my code in App.js
import React from "react";
import { ReactMic } from "react-mic";
import $ from "jquery";
import { findDOMNode } from "react-dom";
import "./App.css";
class App extends React.Component {
handleDisplayForStart = () => {
const startBtn = findDOMNode(this.refs.startBtn);
$(startBtn).addClass("d-none");
const stopBtn = findDOMNode(this.refs.stopBtn);
$(stopBtn).removeClass("d-none");
};
handleDisplayForStop = () => {
const stopBtn = findDOMNode(this.refs.stopBtn);
$(stopBtn).addClass("d-none");
const processBtn = findDOMNode(this.refs.processBtn);
$(processBtn).removeClass("d-none");
};
constructor(props) {
super(props);
this.state = {
blobURL: null,
recordedBlob: null,
record: false,
};
}
startRecording = () => {
this.setState({ record: true });
this.handleDisplayForStart();
};
stopRecording = () => {
this.setState({ record: false });
this.handleDisplayForStop();
};
onData(recordedBlob) {
console.log("chunk of real-time data is: ", recordedBlob);
}
onStop = (recordedBlob) => {
console.log(recordedBlob.blobURL);
const blobURL = recordedBlob.blobURL;
this.setState({ blobURL: blobURL });
this.onUpload();
return recordedBlob.blobURL;
};
onUpload = (recordedBlob) => {
// var form = new FormData();
// form.append("file", recordedBlob);
// fetch("http://localhost:3000/audio", {
// // content-type header should not be specified!
// method: "POST",
// body: form,
// })
// .then(function (response) {
// return response.text();
// })
// .then(function (text) {
// console.log(text); // The text the endpoint returns
// })
// .catch((error) => console.log(error));
};
render() {
return (
<div className="App">
<ReactMic
visualSetting="frequencyBars"
// mimeType='audio/mp3'
record={this.state.record}
className="d-none"
onStop={this.onStop}
onData={this.onData}
/>
<button
ref="startBtn"
className="start-btn"
onClick={this.startRecording}
type="button"
>
START
</button>
<button
ref="stopBtn"
className="stop-btn concentric-circles d-none"
onClick={this.stopRecording}
type="button"
>
STOP
</button>
<button
ref="processBtn"
className="process-btn d-none"
onClick={this.onUpload}
>
Processing..
</button>
<br />
<audio src={this.state.blobURL} controls />
</div>
);
}
}
export default App;
I tried various things from medium blogs and different StackOverflow answers but anything doesn't work correctly.
This may be a bit late, i also came across this problem and i also couldn't find a solution, sharing the solution so it may help others.
code for sending recorded blob file using react-mic to server,
const onStop = (blob) => {
const formData = new FormData();
// if you print blob in console you may get details of this obj
let blobWithProp = new Blob([blob["blob"]], blob["options"]);
formData.append("file", blobWithProp);
const postRequest = {
method: "POST",
body: formData,
};
fetch("http://127.0.0.1:5000/audio_out/", postRequest)
.then(async (res) => {
const data = await res.json();
console.log(data);
if (!res.ok) {
const err = (data && data.message) || res.status;
return Promise.reject(err);
}
})
.catch((err) => {
console.log(err);
});
};
Here onStop() is the callback function which is executed when recording stopped.
On your commented part of your code you are sending recorded blob file directly. I don't know much about it, but if you log the received file on console you may see it is an object file containing blob, options, etc. So, I think we need to create a new Blob file from that. I am just a beginner in web development, may be i am wrong. But the above code solved the problem.

unable to send multipart/form-data to nodejs server

I am trying to send multipart/formdata in my react app. Everytime I hit the POST api using axios, the formdata is always empty.I tried converting to JSON.stringify and key-value method, but nothing seems to work. I do have my headers set as 'Content-Type': 'multipart/form-data'
postList = (e) => {
e.preventDefault();
var postParams;
if(this.state.message && this.state.parent){
postParams = {
message: this.state.message,
chat_m_id: this.state.parent,
depth: (1).toString(),
msg_icon: this.state.msg_icon.name
}
}
else{
postParams = {
message: this.state.message,
chat_m_id: (0).toString(),
depth: (0).toString(),
msg_icon: this.state.msg_icon.name
}
}
console.log(postParams);
let bodyFormData = new FormData();
//approach-one
bodyFormData.append('data',postParams);
//approach-one
// bodyFormData.append('data',JSON.stringify(postParams));
//approach-three
// for (let [key, value] of Object.entries(postParams)) {
// bodyFormData.append(`'${key}'`, JSON.stringify(`${value}`));
// }
console.log(bodyFormData) //this is always empty
axios.post(GlobalVar.BASE_URL+'api/msgtemplate/create', bodyFormData, {headers: GlobalVar.headersFormData})
.then(res => {
console.log(res)
this.props.history.push('/messages')
})
.catch(err => console.log(err.res));
}
I have spent hours on this, please help to solve it.
Here is an example of sending files with axios:
In your case, I have debugged your code here: https://codesandbox.io/s/react-example-ypnbv?fontsize=14&hidenavigation=1&theme=dark
state = { selectedFile: null }
//handler for file change event
fileChangedHandler = event => {
this.setState({ selectedFile: event.target.files[0] })
}
uploadHandler = () => {
const formData = new FormData()
formData.append(
'myFile',
this.state.selectedFile,
this.state.selectedFile.name
)
axios.post('my-domain.com/file-upload', formData)
}

how to upload file like pdf or doc in firestore

I want to upload document files in firestore using redux. i get the file in and passed it as a state to the action file with other datas. following is my code in action file.
const createJob = (project) => {
return (dispatch, getState, {getFirebase, getFirestore}) => {
const firestore = getFirestore();
firestore.collection('Jobs').add({
...project,
postedby:'Employer1',
Documents:project.Documents.name
}).then(()=>{
dispatch({type:'CREATE_JOB', project});
}).catch((err)=>{
dispatch({type:'CREATE_JOB_ERROR', err});
})
}
};
but the data is saved as C:\fakepath\doc1.doc
how to upload the actual file in firestore
Technically you can upload an image to firestore. You need to convert it to base64 text first. Just spent some time figuring it out. I take the selected file from an upload file from browser then I upload it in the callback of the file reader. Hopefully this helps someone out.
function getBase64(file){
var n = document.getElementById('nameU').value;
//name of uploaded file from textbox
var d = document.getElementById('dateU').value;
//date of uploaded file from textbox
var reader = new FileReader();
reader.onerror = function (error) {
console.log('Error: ', error);
};
reader.readAsDataURL(file);
reader.onload = function () {
let encoded = reader.result.split(',');
//you split this to get mimetype out of your base64
addForSale(Date.now().toString(10), {uDesc: n, date: d, uFile: encoded[1]});
// I just used a timestamp as the ID
}
};
function addForSale(id, data) {
var collection = firebase.firestore().collection('forsale');
return collection.doc(id).set(data);}
Hi You cannot directly store the image in firestore.What you have to do is first store the document in firebase storage and get the url as reponse.Once the response is received add the url in documents.
First create an Storage Action in reduce:
import { storage } from '../../../firebase/firebase';
import {
ADD_DOCUMENT_STARTED,
ADD_DOCUMENT_COMPLETED,
ADD_DOCUMENT_ERROR
} from '../../actionTypes/storageActionTypes';
import { toast } from 'react-toastify';
import constants from '../../../config/constants';
export const addDocumentStart = () => ({
type: ADD_DOCUMENT_STARTED
});
export const addDocumentSuccess = () => ({
type: ADD_DOCUMENT_COMPLETED
});
export const addDocumentFailure = () => ({
type: ADD_DOCUMENT_ERROR
});
export const addDocument = (values, pathName) => {
const toastId = toast('Uploading Attachment, Please wait..', {
autoClose: false
});
return (dispatch) =>
new Promise(function(resolve, reject) {
dispatch(addDocumentStart());
const timeStamp = new Date().getTime();
const image = values.document[0];
var name;
if (values && values.documentName) {
name = timeStamp.toString().concat(values.documentName);
} else {
name = timeStamp.toString().concat(image.name);
}
const imageUpload = storage.ref(`${pathName}/${name}`).put(image);
imageUpload.on(
'state_changed',
(snapshot) => {
switch (snapshot.state) {
case 'paused':
reject('Upload is paused');
dispatch(addDocumentFailure('Upload is paused'));
break;
}
},
(error) => {
switch (error.code) {
case 'storage/unauthorized':
reject('Permission Denied');
dispatch(addDocumentFailure('Permission Denied'));
break;
case 'storage/canceled':
reject('Upload Cancelled');
dispatch(addDocumentFailure('Upload Cancelled'));
break;
case 'storage/unknown':
reject('Server Response Error');
dispatch(addDocumentFailure('Server Response Error'));
break;
}
},
() => {
toast.update(toastId, {
render: 'Attachment Uploaded successfully',
type: toast.TYPE.SUCCESS,
autoClose: constants.toastTimer
});
storage
.ref(pathName)
.child(name)
.getDownloadURL()
.then((url) => {
dispatch(addDocumentSuccess());
resolve(url);
});
}
);
});
};
Then in your onsubmit:
this.props.dispatch(addDocument(values, 'Jobs')).then((resp) => {
let documentUrl = resp;
firestore.collection('Jobs').add({
...project,
postedby:'Employer1',
Documents:documentUrl
}).then(()=>{
});

React Dropzone cancel file upload on a button click

I'm using react-dropzone to upload files to my server in my react app. Everything is working great but I want to add a feature where if a file is taking too long to upload due to its size, the user can cancel the process with the click of a button.
<Dropzone
multiple={ false }
accept={ allowedMimeTypes }
onDrop={ this.onDrop }
onDragEnter={ this.onDragEnter }
onDragLeave={ this.onDragLeave }
className={ classes.dropzone }
maxSize={ MAX_UPLOAD_BYTES }
>
</Dropzone>
<button onClick={ this.onCancelUpload }>Cancel</button>
Please advise, if It is possible using react-dropzone. I can't think of a way to stop the event that is already triggered and is uploading the file.
I was able to solve the above problem using the Axios Cancel Token.
Use Axios to handle the upload as a promise.
Create a source at the start of your code.
const CancelToken = axios.CancelToken;
let source = CancelToken.source();
Pass on the source to the request in config.
const {
acceptedFiles
} = this.state;
const uploaders = acceptedFiles.map((file) => {
const formData = new FormData();
// data must be set BEFORE sending file
formData.append('document', file);
const uploadConfig = {
onUploadProgress: (progressEvent) => {
const progressUpload = (progressEvent.loaded * 100) / progressEvent.total;
this.setState({
progressUpload
});
},
cancelToken: source.token,
};
return inkerzApi.post('/uploads/file', formData, uploadConfig)
.then(response => response.data)
.catch(() => console.log('Upload canceled'));
});
Promise.all(uploaders).then((filesMetadata) => {
filesMetadata.forEach((metadata) => {
if (metadata && metadata.mediaLink && metadata.totalPages) {
this.onNewFileUploaded(metadata);
// show success message here
} else if (this.state.uploadCanceled) {
// show cancelation notification here
this.setState({
uploadCanceled: false
});
}
});
this.setState({
acceptedFiles: [],
progressUpload: 0,
});
});
On Cancel Button Click
onCancelUpload = () => {
source.cancel('Operation canceled by the user.');
source = CancelToken.source();
this.setState({ uploadCanceled: true });
}
This worked out for me. Hope this helps others as well.

Resources