Why React doesn't upload image to server? - node.js

I have an app using react and express on the backend and multer to manage the upload. The server side is running properly when I make tests using postman, but if trait to send an image from react the result is unexpected. In that case the file doesn't appear in the uploads folder, however with postman is immediatly.
UploadPage,jsx
const { register, handleSubmit } = useForm();
const onSubmit = async (data) => {
const formData = new FormData();
formData.append('petimage', data.petimage);
try {
const res = await axios.post('/api/petregister', formData);
console.log(res)
} catch (error) {
setError(error.response.data.error);
setTimeout(() => {
setError("");
}, 5000);
}
}
return (
<Container className="mt-5">
<Form onSubmit={handleSubmit(onSubmit)}>
<Form.Group controlId="formFile" className="mb-3">
<Form.Label>Imagen de tu Mascota</Form.Label>
<Form.Control type="file"
label="Select image"
name="petimage"
{...register("petimage")}
/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</Container>
Google Response
The fields with name petimage are the same that I expecified in the backend and used these in the postman tests.
Edit
const store = require('../middlewares/multer');
route.post('/petregister', store.array('petimage', 12), petregister);
The last section of code is the route that is linked with the multer midleware asigned to ssave the images.

When you are making a API call to the backend, it will upload the image to the specific folder that you are defining in the backend like :
const multer = require('multer');
const upload = multer({ dest: 'folder path' });
I think you are getting results unexpected because the name for the image you are giving in formData formData.append('petimage', data.petimage); i.e petimage, it should be the same in the multer fileupload method. You haven't shared the backend code. So, I'm hoping that it may be like this:
var fileUpload = upload.single('petimage'); when the name is the same it will work fine.
If the image is of big size, you can compress it. Please visit this link, it will help you for sure.
https://dev.to/franciscomendes10866/image-compression-with-node-js-4d7h

You can try:
Remove
formData.append('petimage', data.petimage);
and use instead
data.petimage.forEach(pet => formData.append("petimage", pet))

The solution was trait the image as an object. The code is the next:
Object.values(data.petimage).forEach(pet => formData.append('petimage', pet))
Then it worked as expected.

Related

How to convert buffer to file to download on react side

I am using https://www.npmjs.com/package/convert-html-to-pdf to convert html to pdf in nodejs. I have a react frontend and nodejs backend. I want to convert the buffer to a file that people can download on the react side. How can I do this? I don't want to save the file on my servers.
We can set header Content-disposition attachment to indicate that the response is a downloadable file.
Backend: example in Express
const htmlToPDF = new HTMLToPDF(`
<div>Hello world</div>
`);
const buffer = await htmlToPDF.convert();
res.set("Content-Disposition", `attachment; filename="test.pdf"`);
res.set("Content-Type", "application/pdf");
res.send(buffer);
Frontend: example in React
const submit = () => {
window.open("http://localhost:8000"); // Your endpoint here
};
return (
<button onClick={submit}>Download</button>
);
If the endpoint is POST method then window.open won't work. We have to use a form:
<form action="http://localhost:8000" method="POST">
<button type="submit">Download</button>
</form>

Creating Video and Audio Upload Feature

I’m in the beginning stages of planning out my final Capstone project for my Bootcamp.
Two of the features I would like to include are the ability to upload:
Audio
Video
I will be using React.JS for Front-End and Python / Django for server side.
Any suggestions or recommendations for how to approach these upload features?
I’m currently beginning researching how to do this.
you can use html tag input on react
const [file , setFile] = useState();
<input
type="file"
id="fileInput"
onChange={(e) => setFile(e.target.files[0])}
/>
after that you can use FormData() to create file format then send file to api
const data = new FormData();
const filename = username + "_" + file.name;
data.append("name", filename);
data.append("file", file);
try {
api.uploadFile(data);
} catch (error) {
console.log(error);
}
at backend ( django ) I don't know how to handle file requset but you can find it easily . At react side you can use codes at top .

Unable to send api response data from express to react after refreshing the page

I'm learning react and node js with express framework and I'm working on a project where I need to retrieve API data from express to react.
I retrieved data from backend express js where I made a simple json value. My backend server.js code is given below.
server.js
const express = require('express')
const app = express()
const PORT = 3001;
app .get('/api/contents',(req,res)=>{
const contents=[
{
"id":0,
"heading":"Joshua Tree Overnight Adventure",
"content":"A sight in the blue sea..."
},
{
"id":1,
"heading":"Catch waves with an adventure guide",
"content":"Lorem.."
},
{
"id":2,
"heading":"Catch waves with an adventure guide",
"content":"Lorem epsum ..."
}
];
res.json(contents)
})
app.listen(PORT,()=>{
console.log("express server is running...")
})
In react app, I used axios to retrieve those values from backend and tried to pass the api values of content with id= 0 as props in "TheLatestArticles" component. I have updated proxy in package.json in react to connect backend. The below code is the mainhomepage component where it is enclosed with TheLatestArticles component with props value
MainHomePage.js
import axios from 'axios';
import {useState,useEffect} from 'react'
function MainHomePage(){
const [content,setContent]=useState([]);
useEffect(()=>{
const fetchPosts = async ()=>{
const res =await axios.get("/api/contents")
setContent(res.data)
console.log(res)
}
fetchPosts()
},[])
return (
<>
<TheLatestArticle content={content} />
</>
);
}
export default MainHomePage;
TheLatestArticle.js
import cardImage from "./../../Images/card.jpg"
import './TheLatestArticleCard.css';
const TheLatestArticleCard=(props)=>{
console.log(props)
return(
<>
<div className="card">
<div className="image">
<img src={cardImage} alt="cardimg"/>
</div>
<div className="content">
<p className="heading">{props.content.heading}</p>
<p className="body-content">{props.content.content}</p>
<div className="details">
<p className="details-info">Travel <span className="details-info-2">/ August 21 2017</span></p>
</div>
</div>
</div>
</>
)
}
export default TheLatestArticleCard;
When I run the application, It displayed all the api values in the screen given below.
I console.log the api values inside useEffect and it displayed all the api values perfectly.
But when I refresh the page, the api value became undefined and gave me this error
Can you please solve me this issue with the reason behind this error? Thanks a lot!
Try it like this
{(content && content.length > 0) && <TheLatestArticle content={content} />}
Since your API call is async there won't be any data in content initially. After a while, your API is called and data is fetched. Then you will have data. To prevent TheLatestArticle to blow up we add some conditions when to show that component. The error in the screenshot is when you try to use a property heading from content where content is empty.
Now with the condition, TheLatestArticle will not render until there is some data.
Update
You are using <TheLatestArticle content={content} /> and content is assumed to be an object. But as per your code, it's an array. If you are not already using content.map((c)=> <TheLatestArticle content={c} />) you should do that.

How to know file type of some file uploaded in a form with nodeJS?

I would like to know the type of file obtained with req.files in NodeJS. I need this because the file uploaded has to be a photo for the well work of the app. It not only helps me to check that it is not a .jpg since you can make a .txt and change the extension.
The form is the following:
form(class="form add-form space-down" method="POST" enctype="multipart/form-data")
div.title
h1 UPLOAD NEW PROGRESS
div.form-group
label(for="weight") Weight:
input(type="number" name="weight" class="form-control" placeholder="Enter your weight")
div.form-group
label(for="front") Upload a front photo
input(type="file" name="front" accept="image/*")
div.form-group
label(for="from_side") Upload a from side photo
input(type="file" name="from_side" accept="image/*")
div.form-group
label(for="backwards") Upload a backwards photo
input(type="file" name="backwards" accept="image/*")
And the router handle is the following to obtain the photos uploaded:
routerProgress.post("/home/upload-progress", (req, res) => {
const front = req.files.front;
const from_side = req.files.from_side;
const backwards = req.files.backwards;
}
How can I be sure that front, from_side and backwards are photos?
If anyone has any idea how to do it, I would be very grateful if you could help me.
You can do something like this. Create a function which returns the extension of the file and you can check if it is a valid image extension or not.
routerProgress.post("/home/upload-progress", (req, res) => {
const front = getFileExtension(req.files.front);
const from_side = getFileExtension(req.files.from_side);
const backwards = getFileExtension(req.files.backwards);
if (front) {
// its an image, do something
}
}
function getFileExtension (filename) {
const allowedFileExt = ['JPEG', 'JPG', 'PNG', 'GIF', 'TIFF', 'PSD', 'PDF']; // you can add as per your requirement
const fileExt = /[^.]+$/.exec(filename);
return allowedFileExt.includes(fileExt[0].toUpperCase());
}
If that is the case, you should use mmmagic, it checks the content of the file instead checking only the extension. Try using this lib it will be more useful for your use case. Also, take a look at this npm package image-type

Uploading a file and sending it to the backend with React and Node

I need to upload a file in react and send it to the Node backend.
Since I never worked with uploading and sending files before, this is a little troubling for me.
So far I found this:
// this creates a React component that can be used in other components or
// used directly on the page with React.renderComponent
var FileForm = React.createClass({
// since we are starting off without any data, there is no initial value
getInitialState: function() {
return {
data_uri: null,
};
},
// prevent form from submitting; we are going to capture the file contents
handleSubmit: function(e) {
e.preventDefault();
},
// when a file is passed to the input field, retrieve the contents as a
// base64-encoded data URI and save it to the component's state
handleFile: function(e) {
var self = this;
var reader = new FileReader();
var file = e.target.files[0];
reader.onload = function(upload) {
self.setState({
data_uri: upload.target.result,
});
}
reader.readAsDataURL(file);
},
// return the structure to display and bind the onChange, onSubmit handlers
render: function() {
// since JSX is case sensitive, be sure to use 'encType'
return (
<form onSubmit={this.handleSubmit} encType="multipart/form-data">
<input type="file" onChange={this.handleFile} />
</form>
);
},
});
Source: https://fitacular.com/blog/react/2014/06/23/react-file-upload-base64/
But now I basically just end up with some sort of string. But I need to send that file via REST to my Express backend, which needs to save that file in CouchDB.
What is the best/easiest way to accomplish that?
If you are using body-parser, know that it handles json and url encoded forms, not multipart data !
You should use an other module.
For more infos, give a look at : File uploading with Express 4.0: req.files undefined

Resources