I want to send an image with react axios and return a character string, but I have a question here.
The backend is an API that puts an image and returns a character string.
I want to ask a question.
How can I display the image to be sent on the screen?
How can I display the string returned after sending the image?
import React from 'react'
import axios from 'axios';
class FileUpload extends React.Component{
constructor(){
super();
this.state = {
selectedFile:'',
}
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
this.setState({
selectedFile: event.target.files[0],
})
}
submit(){
const data = new FormData()
data.append('file', this.state.selectedFile)
console.warn(this.state.selectedFile);
let url = "http://localhost:8000/upload.php";
axios.post(url, data, { // receive two parameter endpoint url ,form data
})
.then(res => { // then print response status
console.log(res.data)
})
}
render(){
return(
<div>
<div className="row">
<div className="col-md-6 offset-md-3">
<br /><br />
<h3 className="text-white">React File Upload Example - Tutsmake.com</h3>
<br />
<div className="form-row">
<div className="form-group col-md-6">
<label className="text-white">Select File :</label>
<input type="file" className="form-control" name="upload_file" onChange={this.handleInputChange} />
</div>
</div>
<div className="form-row">
<div className="col-md-6">
<button type="submit" className="btn btn-dark" onClick={()=>this.submit()}>名前確認</button>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default FileUpload;
If I understood
this is how to get a preview of selected image
const [file] = e.target.files;
setImgPrev(URL.createObjectURL(file));
// imgPrev state will be the src of your preview image
and to get the string that returned after sending the html request you have to listen to the response that will come from axios
axios.post(url, data)
.then(res => setRes(res))
.catch(err => return err)
I've made image uploader and preview the uploaded image before sent to the BE with API. I also use normal html input with type file. May be my code can be used in yours.
const handleImageChange = (value) => {
let reader = new FileReader();
const image = value.target.files[0];
setSavedFile(image);
reader.onload = () => {
setMainImage({
img: reader.result,
});
};
reader.readAsDataURL(image);
}
...
...
<input
onChange={(e) => handleImageChange(e)
/>
the image that will rendered saved with setMainImage(), the image source is in reader.result. For the setSavedFile is used to save the file uploaded.
For the question number 2, you can normally save the response from the API to state and show the state in the html element
Related
I've trying to:
Upload image to firebase storage
create field 'fileUrl' in Firestore under the 'articles' document
reference the doc in Firestore so that each image knows to which article it is assigned.
I managed to do all of that in a way but the issue is that when I submit the form with a title, content and image, it creates a new document in Firestore with just a the image ('fileUrl'), instead of creating a document that includes the rest of the form's data.
I know that this is probably because in my UploadFile.js I'm creating a new document but how do I join the Field created in UploadFile.js with the fields in AddArticle.js?
I'm also getting ''Unhandled Rejection (TypeError): Cannot read property 'state' of undefined' for this line:
firebase.firestore().collection('articles').doc(this.state.documentId).update({
fileUrl: fileUrl
})
UploadFile.js
import React from "react";
import firebase from '../Firebase';
function UploadFile() {
const [fileUrl, setFileUrl] = React.useState(null);
const onFileChange = async (e) => {
const file = e.target.files[0]
const storageRef = firebase.storage().ref()
const fileRef = storageRef.child(file.name)
await fileRef.put(file);
setFileUrl(await fileRef.getDownloadURL().then(fileUrl => {
firebase.firestore().collection('articles').doc(this.state.documentId).update({
fileUrl: fileUrl
})
.then(() => {
setFileUrl('')
})
} ));
};
return (
<>
<input type="file" onChange={onFileChange} />
<div>
<img width="100" height="100" src={fileUrl} alt=''/>
</div>
</>
);
}
export default UploadFile;
AddArticle.js
import React, { Component } from 'react';
import firebase from '../Firebase';
import UploadFile from '../components/UploadFile';
class AddArticle extends Component {
constructor() {
super();
this.ref = firebase.firestore().collection('articles');
this.state = {
title: '',
content: '',
fileUrl: ''
};
}
onChange = (e) => {
const state = this.state
state[e.target.name] = e.target.value;
this.setState(state);
}
onSubmit = (e) => {
e.preventDefault();
const { title, content, fileUrl } = this.state;
this.ref.add({
title,
content,
fileUrl
}).then((docRef) => {
this.setState({
title: '',
content: '',
fileUrl: '',
documentId: docRef.id
});
this.props.history.push("/")
})
.catch((error) => {
console.error("Error adding document: ", error);
});
}
render() {
const { title, content, fileUrl } = this.state;
return (
<div className="container">
<br></br><br></br><br></br>
<div className="panel panel-default">
<div className="panel-heading">
<h3 className="panel-title text-center">
Create a new article
</h3>
</div>
<br></br><br></br>
<div className="panel-body">
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label for="title">Title:</label>
<input type="text" className="form-control" name="title" value={title} onChange={this.onChange} placeholder="Title" />
</div>
<div className="form-group">
<label for="content">Content:</label>
<textArea className="form-control" name="content" onChange={this.onChange} placeholder="Content" cols="80" rows="20">{content}</textArea>
</div>
{/* <input type="file" onChange={this.onFileChange} /> */}
<UploadFile onChange={this.onChange} value={fileUrl}/>
<button type="submit" className="btn btn-success">Submit</button>
</form>
</div>
</div>
</div>
);
}
}
export default AddArticle;
Each time you call firebase.firestore().collection('articles').add(...), you add a new document to the database. Since you call that in both AddArticle and in UploadFile, your image URL and the other fields indeed will end up in separate documents.
The way you're handling the file upload is a bit unusual to me, as I'd normally expect that upload to happen when the other fields are also submitted. Right now, it's not clear to me what the image belong to, as J.A.Hernández also commented.
Either way: you'll need to remove one of the firebase.firestore().collection('articles').add(...) calls and instead pass the document ID into that call. Say that you first add the text fields and then upload the image, the UploadFile can then update the document with:
firebase.firestore().collection('articles').doc(documentId).update({
fileUrl: fileUrl
})
One way to pass the document ID from the to is by keeping it in the state:
this.ref.add({
title,
content,
fileUrl
}).then((docRef) => {
this.setState({
title: '',
content: '',
fileUrl: '',
documentId: docRef.id
});
this.props.history.push("/")
})
And then:
firebase.firestore().collection('articles').doc(this.state.documentId).update({
fileUrl: fileUrl
})
I am currently creating a webapplication using React.js on the frontend that does image classification. One problem I've run into is being able to make an image tensor using the fromPixels method of Tensorflow.js. The error I recieve is:
Unhandled Rejection (Error): pixels passed to tf.browser.fromPixels() must be either an HTMLVideoElement, HTMLImageElement, HTMLCanvasElement, ImageData in browser, or OffscreenCanvas, ImageData in webworker or {data: Uint32Array, width: number, height: number}, but was String
Also, here is my code:
async onSubmit(e){
e.preventDefault()
const model = await tf.loadLayersModel('http://localhost:81/model/model.json')
const reader = new FileReader()
reader.readAsDataURL(this.state.image)
const tensor = tf.browser.fromPixels(reader.result)
.resizeNearestNeighbor([224,224])
.toFloat()
.expandDims()
const predictions = await model.predict(tensor).data()
console.log(predictions)
const formdata = new FormData()
formdata.append('caption',this.state.caption)//key-value pair
formdata.append('description',this.state.description)
formdata.append('date', this.state.date)
formdata.append('image',this.state.image)
//creating a formdata object
console.log('Image uploaded !')
axios.post('http://localhost:3002/images',formdata)
.then(res=>console.log(res.data))
//window.location = '/results'
//this will go to the 'results' page--where the image is displayed
}
Also, for context, here is my render function:
render(){
return(
<div>
<form onSubmit = {this.onSubmit}>
<div className="form-group">
<label>Caption:</label>
<input type="text"
required
className="form-control"
value={this.state.caption}
onChange={this.onChangeCaption}
/>
</div>
.....{//removed some code not relevant to the question here}
<div className="form-group">
<label>Choose a File</label>
<input type="file"
className="form-control"
onChange={this.onChangeImage}
/>
</div>
<div className="form-group">{//submit button}
<input type="submit" value = "Upload Data" className = "btn btn-primary"/>
</div>
</form>
</div>
)
}
Basically, the onSubmit function is called when the form is submitted and when I am about to make a post request to my REST API.
I have no idea how to preprocess the file object stored in this.state.image. Any ideas?
You can use FileReader to create an img element and load it from there:
const image = document.createElement("img");
reader.onload = async (event) => {
image.src = event.target.result
document.body.append(image);
image.onload = async () => {
tf.browser.fromPixels(image);
}
}
I hope you are well especially in the covid crisis.
im trying to upload an image using axios but it apears always to be null and i cant fix it.
i used encType="multipart/form-data" , and <meta name="csrf-token" content="{{ csrf_token() }}" and nothing works for me ; i think the problem is within the onChange{} despite its from the official ReactJs documentation.
here my component :
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
export default class MedcineRegister extends Component
{
constructor(props)
{
super(props);
this.state = {
json:JSON.parse(props.data),//data received from a laravel controller used to implement the select option menu down below.
Specialite: '1',//initialization
image: '',
};
this.onChangeValue = this.onChangeValue.bind(this);
this.onSubmitButton = this.onSubmitButton.bind(this);
}
onChangeValue(e) {
this.setState({
[e.target.name]: e.target.value,//->this line is working only for Specialite
});
}
async onSubmitButton(e) {
e.preventDefault();
try {
const response = await axios.post('/medcine/registerR',{
Specialite: this.state.Specialite,
image: this.state.image,
});
console.log(response.data);//[{…}]0: {Specialite: "8" , image: null}
} catch (error) {
console.log("error in MedcineRegister.js");
}
}
componentDidMount () {
}
render()
{
return (
<div className="container">
<div className="card-body">
<form encType="multipart/form-data" onSubmit={this.onSubmitButton}>
<div className="col-md-6">
<select onChange={this.onChangeValue} name="Specialite" value={this.state.value} autoFocus>
{this.state.json.map(i => (
<option className="form-control" value={i.id}>{i.nom}</option>
))}
</select>
</div>
<div className="col-md-6">
<input id="file" type="file" name="file" onChange={this.onChangeValue} autoFocus/>
</div>
<div className="form-group row mb-0">
<button className="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
);
}
}
if (document.getElementById('mr')) {
var data = document.getElementById(('mr')).getAttribute('data');
ReactDOM.render(<MedcineRegister data={data}/>, document.getElementById('mr'));
}
as you see guys the consol is alwas showing me "image" : null , any idea how to solve it please
The name attribute of your file input is "file".
So the this.setState in the onChangeValue is actually:
this.setState({
"file": e.target.value
});
Image is never being set.
And if it's a file that you want to post, there are a few changes to be made.
The setState in onChangeValue function should be:
this.setState({
image: e.target.files[0]
});
Data to be posted has to be sent as formData
const formData = new FormData();
formData.append("Specialite", this.state.Specialite);
formData.append("image", this.state.image);
const response = await axios.post("/medcine/registerR", formData, {
headers: {
"Content-Type": "multipart/form-data"
}
});
I am re-creating a basic chat from a previous project (formerly used Bootstrap and Socket) and this go around I am utilizng a React component to render the chat (which consists of an input area for user name, an input area for text content, and a div where the username and message inserted should appear together i.e. "BugsBun01: "Whats up Doc?!"). I am unsure whether or not I should have the empty div where chat content belongs in a separate React component (my end goal is to have the parent component to immediately update the chat area whilst writing the content from the insert fields (username and text content) to the database collection)
I have Mongo database which contains a collection for chats (username/message) but my question is
A) how do I go about using axios to store the inserted username and text in the collection, and
B) once stored how would I allow the parent component (React) to immediately update them to the empty div (chatArea) from the mongo database so that upon page refresh, the users' old chats are still present?
Do I need componentDidMount()?
Do I need any middleware in my server.js file? (bodyparser etc.)
I am fairly new to using React js so bear with me. Also this is a fairly barebones chat that is focusing on functionality.
class Chat extends React.Component {
constructor(props){
super(props);
this.state = {
username: '',
message: '',
messages: []
};
}
render() {
return (
<div id="myChat">
<div id="status"></div>
<input type="text" id="username" class="form-control" placeholder="Enter Username..." value={this.state.username} onChange={ev => this.setState({username: ev.target.value})}>
</input>
<div id="chat">
<br></br>
<div class="card">
<div id="messages" class="card-block">
{this.state.messages.map(message => {
return (
<div>{message.author}: {message.message}</div>
)
})}
</div>
</div>
<br></br>
</div>
<textarea id="textarea" class="form-control" placeholder="Enter message..." value={this.state.message} onChange={ev => this.setState({message: ev.target.value})} ></textarea>
</div>
);
}
}
You have to need ur server for that is not necessary to use axios for that u can manage all thing with ur socket connection.
Server.js that manage ur backend which u want play with the database.
Server.js: implements a start the socket.
const io = require('socket.io')();
const AVATAR = 'https://i1.wp.com/tricksmaze.com/wp-content/uploads/2017/10/Stylish-Girls-Profile-Pictures-11.jpg';
const NAME = '#zoya';
io.on('connection', function (client) {
// console.log('client Id::', client.id)
//chat message
client.on('chat-message', function (messages) {
let { message } = messages;
let messageObj = {
sender: NAME,
avatar: AVATAR,
message
}
client.emit('chat-message', messageObj);
});
//disconnects...
client.on('disconnect', function () {
console.log('disconnect client Id::', client.id)
});
});
const port = 8000;
io.listen(port);
console.log('listening on port : ', port);
on client side.
'use static';
import React, { Component } from 'react';
import openSocket from 'socket.io-client';
const SERVER = `http://localhost:8000/`;
const NAME = '#asif';
const AVATAR = 'https://pbs.twimg.com/profile_images/874276197357596672/kUuht00m_400x400.jpg';
const AVATAR1 = 'https://i1.wp.com/tricksmaze.com/wp-content/uploads/2017/10/Stylish-Girls-Profile-Pictures-11.jpg';
class App extends Component {
constructor(props) {
super(props);
this.state = {
typing: '',
messages: []
}
this.socket = openSocket(SERVER);
this.chatMessage = this.chatMessage.bind(this);
}
componentDidMount() {
this.chatMessage();
}
chatMessage() {
this.socket.on('chat-message', (messageObj) => {
let { messages } = this.state;
messages.push(messageObj);
this.setState({ messages: messages })
})
}
sendMessage = () => {
let { messages, typing } = this.state;
if (typing && typing !== '') {
const message = typing;
this.setState({ typing: '' })
let messageObj = {
sender: NAME,
avatar: AVATAR,
message
}
messages.push(messageObj);
this.setState({ messages: messages })
this.socket.emit('chat-message', messageObj);
} else {
alert(`Message can't empty`);
}
};
renderItem() {
return this.state.messages.map((item,key)=>{
return (
<div >
<image src={ item.avatar } />
<div }>
<span >{item.sender}</span>
<span >{item.message}</span>
</div>
</div>
);
})
}
render() {
return (
<div >
<div >
<h1 >
Chat App
</h1>
</div>
{this.renderItem()}
<div >
<input
Type="text"
ref={ref => { this._messageInput = ref }}
placeholder="Type Message..."
value={this.state.typing}
onChangeText={text => this.setState({ typing: text })}
/>
<button onClick={() => this.sendMessage()}>
<span >Send</span>
</button>
</div>
</div>
);
}
}
export default App;
hope this help full for u.
<div className="mb-1">
Image <span className="font-css top">*</span>
<div className="">
<input type="file" id="file-input" name="ImageStyle"/>
</div>
</div>
This is the snippet i provided that i was using to pick the file from the device in react js,
Using this i can select the file and that filename is also shown as well
What i want is now to store this file on S3 or anywhere and get its URL from there and POST it to my server using fetch api call.
import React, { useState } from "react";
const UploadAndDisplayImage = () => {
const [selectedImage, setSelectedImage] = useState(null);
return (
<div>
<h1>Upload and Display Image usign React Hook's</h1>
{selectedImage && (
<div>
<img
alt="not found"
width={"250px"}
src={URL.createObjectURL(selectedImage)}
/>
<br />
<button onClick={() => setSelectedImage(null)}>Remove</button>
</div>
)}
<br />
<br />
<input
type="file"
name="myImage"
onChange={(event) => {
console.log(event.target.files[0]);
setSelectedImage(event.target.files[0]);
}}
/>
</div>
);
};
export default UploadAndDisplayImage;
Upload the image from your file and display it on your page in react,
you can also get the image object in the state when we select the image
to display on the webpage you have to convert the image object to object using URL.createObjectURL(fileObject)
import React, { Component } from "react";
class DisplayImage extends Component {
constructor(props) {
super(props);
this.state = {
image: null
};
// if we are using arrow function binding is not required
// this.onImageChange = this.onImageChange.bind(this);
}
onImageChange = event => {
if (event.target.files && event.target.files[0]) {
let img = event.target.files[0];
this.setState({
image: URL.createObjectURL(img)
});
}
};
render() {
return (
<div>
<div>
<div>
<img src={this.state.image} />
<h1>Select Image</h1>
<input type="file" name="myImage" onChange={this.onImageChange} />
</div>
</div>
</div>
);
}
}
export default DisplayImage;
If you want to upload image and post it to an API. Then you install react-image-uploader. It saves the image to your local port and also in your database by raising a POST request.
This code let you upload image to the server,the backend code is written in nestjs,and display the image which will be uploaded.I have used the formdata.
import React, { useEffect, useState } from "react";
function Product() {
const { REACT_APP_REST } = process.env;
const [file, setFile] = useState([]);
const handleFile = event => {
setFile(
URL.createObjectURL(event.target.files[0])
);
const formData = new FormData();
formData.append("fileupload", event.target.files[0]);
fetch(REACT_APP_REST + "/product/upload", {
method: 'POST',
body: formData,
dataType: "jsonp"
})
};
return (
<>
<Container fluid>
<Col md="4">
<Card className="card-user">
<img src={file} />
<Card.Body>
<Form.Group>
<label>IMAGE</label>
<Form.Control
type="file"
required="required"
onChange={handleFile}
></Form.Control>
</Form.Group>
</Card.Body>
<hr></hr>
</Card>
</Col>
</Container>
</>
);
}
export default Product;
using react-uploady you can do this very easily:
import React from "react";
import Uploady from "#rpldy/uploady";
import UploadButton from "#rpldy/upload-button";
import UploadPreview from "#rpldy/upload-preview";
const filterBySize = (file) => {
//filter out images larger than 5MB
return file.size <= 5242880;
};
const App = () => (
<Uploady
destination={{ url: "my-server.com/upload" }}
fileFilter={filterBySize}
accept="image/*"
>
<UploadButton />
<UploadPreview />
</Uploady>
);
Failed to execute 'createObjectURL' on 'URL': Overload resolution failed.
For some reason I coudn't use URL.createObjectURL(image) as
const [image, setImage] = useState(null);
const [imgURL, setImgURL] = useState();
<img src={URL.createObjectURL(image)}/>
So I save the Url in the state for instant display on the button click method. This worked!
setImgURL(URL.createObjectURL(image));
Unfortunately, I was still getting the same error when I use useEffect.
useEffect(() => {
setImgURL(URL.createObjectURL(image));
}, [image]);