first of all I had a project that i needed to send an image to AWS S3 bucket .. so I need first to send image from front end to back end so i used Axios to do that.. but now i needed to copy this code in my new application so i tested my old application first and it successfully worked .. but when i created that new application it shows me that error.
enter image description here
sounds like the route i am giving it wrong but i checked alot of times its not wrong at all
here is my frontend code
import { useState } from 'react'
import axios from 'axios'
async function postImage({image, description}) {
const formData = new FormData();
formData.append("image", image)
formData.append("description", description)
const result = await axios.post('/images', formData, { headers: {'Content-Type': 'multipart/form-data'}})
.catch(function (error) {
console.log(error);
});
return result.data
}
function Image() {
const [file, setFile] = useState()
const [description, setDescription] = useState("")
const [images, setImages] = useState([])
const submit = async event => {
event.preventDefault()
const result = await postImage({image: file, description})
setImages([result.image, ...images])
}
const fileSelected = event => {
const file = event.target.files[0]
setFile(file)
}
return (
<div className="App">
<form onSubmit={submit}>
<input onChange={fileSelected} type="file" accept="image/*"></input>
<input value={description} onChange={e => setDescription(e.target.value)} type="text"></input>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default Image;
the error that i am catching is
Error: Request failed with status code 404
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:62)
here is my backend code
const express = require("express");
const fs = require("fs");
const util = require("util");
// const unlinkFile = util.promisify(fs.unlink);
const path = require("path");
const multer = require("multer");
const upload = multer({ dest: "uploads/" });
// const { uploadFile, getFileStream } = require("./s3");
const app = express();
app.post('/images', upload.single('image'), async (req, res) => {
// const file = req.file
console.log(file)
})
const port = process.env.PORT || 5000;
app.listen(port);
console.log("App is listening on port " + port);
Related
I am trying to upload a file to the API, sort the numbers and then return the result in another text file that is available to download. I upload the file, and when I start the calculation I get the Internal Server Error. The API is running on port 3000 and I start the React App.js on port 3001.
Is there something I'm doing wrong?
This is the API's app.js:
const express = require('express');
const multer = require('multer');
const bodyParser = require('body-parser');
const fs = require('fs');
const app = express();
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
app.use(bodyParser.text({ type: 'text/plain' }));
app.post('/sort', upload.single('inputFile'), (req, res) => {
console.log(req.file)
const input = req.file.buffer.toString().split('\n').map(Number);
const result = input.sort((a, b) => b - a);
const resultText = result.join('\n');
fs.writeFile('result.txt', resultText, (err) => {
if(err) throw err;
res.send('File succesfully sorted!');
});
res.set('Content-Type', 'text/plain');
res.send(resultText);
});
app.listen(3000, () => {
console.log('API is listening on port 3000');
});
This is the React App.js:
const [inputFile, setInputFile] = useState(null);
const [result, setResult] = useState(null);
const [processingTime, setProcessingTime] = useState(null);
const handleFileUpload = (event) => {
setInputFile(event.target.files[0]);
};
const startCalculation = async (event) => {
event.preventDefault();
const startTime = performance.now();
const formData = new FormData();
formData.append('inputFile', inputFile);
console.log(inputFile)
const response = await fetch("http://localhost:3000/sort", {
method: 'POST',
body: formData,
mode: 'no-cors',
});
const data = await response.text();
console.log(data);
setResult(data);
setProcessingTime(performance.now() - startTime);
};
const handleDownload = (event) => {
event.preventDefault();
const file = new Blob([result], {
type: 'text/plain'
});
const fileURL = URL.createObjectURL(file);
const link = document.createElement('a');
link.href = fileURL;
link.download = 'result.txt';
link.click();
};
The issue is on the client you are setting the input name to inputFile, however, on the backend you are telling Multer that the input name is myFile.
Change from this:
upload.single("myFile")
To this:
upload.single("inputFile")
I am following a mern stack tutorial and trying to send data to api from react js form which is:
import axios from 'axios'
import { useState } from 'react'
import './share.css'
export default function Share() {
const [username, setUsername] = useState('')
const [file, setFile] = useState(null)
const handleSubmit = async(e)=>{
e.preventDefault()
const newPost = {
username: username
}
if(file){
const data = new FormData()
const fileName = file.name
data.append('name', fileName)
data.append('file', file)
newPost.pic = fileName
console.log(newPost)
try{
await axios.post('http://localhost:5000/upload', data)
}catch(err){
console.log(err)
}
}
try{
await axios.post('http://localhost:5000/post/post', newPost)
}catch(err){
console.log(err)
}
}
return (
<form className='share' onSubmit={handleSubmit}>
<div className='shareTop'>
<span>M</span>
<input className='shareInput' type='text' placeholder="What's happening?" onChange={(e)=>setUsername(e.target.value) } />
</div>
<div className='shareBottom'>
<div className='bottomIcons'>
<label htmlFor='file'>
<i class="fa-solid fa-face-meh"></i>
<input type='file' style={{display:"none"}} name='file' id='file' onChange={(e)=>setFile(e.target.files[0])} />
</label>
<i class="fa-solid fa-calendar"></i>
<i class="fa-solid fa-notes"></i>
<i class="fa-solid fa-bookmark"></i>
</div>
<button type='submit'>Tweet</button>
</div>
</form>
)
}
and my index js (serve side) file is:
const express = require('express')
const app = express()
const mongoose = require('mongoose')
const helmet = require('helmet')
const morgan = require('morgan')
const postRoute = require('./routes/posts')
const multer = require('multer')
const bodyParser = require('body-parser')
const cors = require('cors')
app.use(cors())
app.use(express.json())
app.use(morgan('common'))
app.use(helmet())
app.use(express.static('uploads'))
const storage = multer.diskStorage({
destination: function(req, file, cb){
cb(null, './uploads')
},
filename: function(req, file, cb){
cb(null, req.body.name)
}
})
const upload = multer({storage});
app.post('/upload', upload.single('file'), (req, res)=>{
})
app.use('/post/', postRoute)
mongoose.connect('mongodb://localhost:27017/twitter').then(()=>{
console.log("Connected to Database")
})
app.listen(5000, ()=>{
console.log('Listening')
})
and posts route is:
const express = require('express')
const router = express.Router()
const Post = require('../models/Post')
router.post('/post', async(req, res)=>{
const post = new Post({
username: req.body.username,
pic: req.body.pic
})
try{
const newPost = await post.save()
console.log("post has been saved")
res.status(200).json("Post has been saved")
}catch(err){
res.status(500).json(err)
}
})
router.put('/:id', async(req, res)=>{
const post =await Post.findByIdAndUpdate(req.params.id, {$set:req.body})
res.status(200).json("Account has been updated")
})
router.get('/', async (req, res)=>{
const posts = await Post.find()
res.status(200).json(posts)
})
router.delete('/', async(req, res)=>{
await Post.deleteMany()
})
module.exports = router
So the problem is that the file is being uploaded to backend but the data does not, after doing some research i realized that the second try and catch block where i am posting the content is not being called, just the first api where we upload file is being called, can someone tell me what am i doing?
I am making a pinterest clone so I need to upload images but I cant fetch files from frontend to back end(with axios)
this is the server
I tested so many stuff but I can't understand where is the flaw. The app stores the photo and it seems that the problem happens when I want to get the data to backend but only files cuz I can fetch string from frontend
const express = require('express');
const app = express()
const mongoose = require('mongoose')
const cors = require('cors')
const Photo = require('./models/Photo')
const multer = require('multer')
//MiddleWare
app.use(cors())
app.use(express.json())
mongoose.connect('', () =>{
console.log('Connected to DB..')
})
// storage
const Storage = multer.diskStorage({
destination: 'uploads',
filename: (req, file,cb) =>{
cb(null, file.originalname)
}
})
const upload = multer({
storage: Storage,
}).single('testImage')
app.post('/add', async(req, res) =>{
console.log(req.files)
})
app.listen(3001, () =>{
console.log('Listening..')
})
And this is client side
/* eslint-disable jsx-a11y/alt-text */
/* eslint-disable react/jsx-no-comment-textnodes */
import React, { useState, useRef } from "react";
import NotificationsIcon from "#mui/icons-material/Notifications";
import AddAPhotoIcon from "#mui/icons-material/AddAPhoto";
import "./Header.css";
import axios from "axios"
const Header = ({gallery, setGallery}) => {
const [open, setOpen] = useState(false);
const [photo, setPhoto] = useState('')
const handleModel = (e) => {
setOpen(!open);
};
const handlePhoto = (e) => {
setPhoto(e.target.files[0])
}
const handleSubmit = e=>{
e.preventDefault();
setOpen(!open);
console.log(photo)
axios.post('http://localhost:3001/add',{photo: photo})
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
}
return (
<div className="header">
<div className="nav">
<img
src="https://i.pinimg.com/originals/0d/ea/4a/0dea4ad3030467e2f65cde00935ba62b.png"
className="logo"
/>
<input type="text" className="search-input" placeholder="Search" />
<NotificationsIcon color="action" fontSize="large" className="icon" />
<AddAPhotoIcon
color="action"
fontSize="large"
className="add-icon icon"
onClick={handleModel}
/>
</div>
{open ? (
<form onSubmit={handleSubmit} className="popup" encType='multipart/form-data'>
<input
type="file"
accept=".png, .jpg, .jpeg"
filename='testImage'
onChange={handlePhoto}
/>
<button >Submit</button>
</form>
) : (
""
)}
</div>
);
};
export default Header;
Server console logs undefined when I upload an image but why tho??
Multer returns you a middleware when you invoke the multer() function.
so in your case you should add the middleware to your route.
const upload = multer({
storage: Storage,
}).single('testImage');
app.post('/add', upload ,async(req, res) =>{
console.log(req.file)
})
Now your route '/add' will look for the key testImage in the multipart/form-data.
You need to pass the upload as formData
const formData = new FormData();
formData.append('files', photo); //this matches req.files
const res = await axios.post('http://localhost:3001/add', formData, {
headers: formData.getHeaders() //formData will set content-type etc
});
and update route to use middleware
app.post('/add', upload, async(req, res) => {})
All I want to achieve is to upload the image in react frontend, save it in local public/images folder in backend and display the uploaded images back in frontend. So far I have managed to upload the files to backend. I cant figure out how to display the files in frontend. I want to make a get request to send the image files to frontend
express code:
express code image
const express = require("express");
const multer = require("multer");
const cors = require("cors");
const app = express();
app.use(cors());
app.use(express.static("./public"));
var storage = multer.diskStorage({
destination: "./public/images",
filename: function (req, file, cb) {
cb(null, Date.now() + '-' +file.originalname )
}
})
var upload = multer({ storage: storage }).array('file');
app.post('/upload',function(req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
return res.status(500).json(err)
} else if (err) {
return res.status(500).json(err)
}
return res.status(200).send(req.file)
})
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, ()=> {
console.log("server started at port "+PORT);
});
React frontend code:
import React, { useState } from 'react';
import axios from "axios";
const ImageForm = () => {
const [file, setFile] = useState(null);
const handleFileChange = (event) => {
setFile(event.target.files);
console.log(file)
}
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData();
for(var x = 0; x<file.length; x++) {
data.append('file', file[x])
}
axios.post("http://localhost:5000/upload", data)
.then(res => {
console.log(res.statusText)
})
}
return (
<div>
<form >
<div className="form-group" >
<label htmlFor="file">Upload File:</label>
<input
className="form-control-file mb-3"
type="file" id="file"
accept=".jpg"
multiple
onChange={handleFileChange}
/>
<button
className="btn btn-primary mt-3"
onClick={handleSubmit}
>Upload</button>
</div>
</form>
{/* Display Image Here */}
</div>
);
}
export default ImageForm;
res: response
error: err
Firstly, create a state:
const [imgFile, setImgFile] = useState('');
Then, replace the following part of your code:
axios.post("http://localhost:5000/upload", data)
.then(res => {
setImgFile('http://localhost:5000/public/images/'+res.data.filename)
})
Add this after the form tag
<img src={imgFile} alt="img"/>
Just in case the image does not load, add this in the express code:
app.use('/public/images', express.static(__dirname + '/public/images/'));
So this is the first time Im trying to upload files to the server, and I started following a tutorial to builöd backend and frontend in react, but I cant get it to work.
My backend is now working with some adjustments, Ive been trying it out in postman and my uploaded files end up in the uploads folder.
But when I try it out in the browser with my frontend I cant get it to work, I only get my console.log string 'msg No file uploaded', but not the actual msg from backend.
Anyone that can see where I written wrong?
I've compared it with similar code, I've tried to change a bunch of stuff but I can't see why or what is missing?
server.js
const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')
const fileUpload = require('express-fileupload')
const path = require("path")
var moment = require('moment')
const port = process.env.PORT || 5000
const app = express()
// enable files upload
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(fileUpload())
app.use(express.static('./public'));
//middlewares
app.use(cors())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {
res.send('hello world')
})
app.get('/upload', (req, res) => {
console.log('req.files.file', req.files.file)
res.json(req.files.file) //files should give the uploaded file
res.json(req.body.file) //body should give the name and description field
})
//Upload endpoint
app.post('/upload', (req, res) => {
try {
if (req.files === null) {
return res.status(400).json({ msg: 'No file uploaded' })
}
const file = req.files.file
const fileName = file.name
//const description = req.body
//const date = moment().add(10, 'days').calendar()
const extension = path.extname(fileName)
const allowedExtensions = /xml|jpeg|jpg|pdf/
if (!allowedExtensions.test(extension)) throw "Unsupported file type!";
//.mv() = move the file to current dir/client(react)/public
file.mv(`${__dirname}/client/public/uploads/${file.name}`)
res.json({
message: 'File uploaded successfully!',
fileName: file.name,
description: req.body,
date: moment().add(10, 'days').calendar(),
filePath: `/uploads/${file.name}`
})
} catch (err) { //catch if path doesn't exist
console.error(err)
//500 server error
return res.status(500).send(err)
}
})
//make uploads directory static
app.use(express.static('uploads'));
//Delete endpoint
//app.delete('/upload')
// Start the server
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`)
})
fileUpload.js
import React, { useState } from 'react'
import axios from 'axios'
const FileUpload = () => {
const [file, setFile] = useState('')
const [fileName, setFileName] = useState('Choose File')
const [uploadedFile, setUploadedFile] = useState({});
const onChange = (e) => {
setFile(e.target.files[0])
setFileName(e.target.files[0].name) //this should change the name in {fileName}
}
const onSubmit = async e => {
e.preventDefault()
const formData = new FormData()
formData.append('file', file)
console.log('file', file)
try {
const res = await axios.post('/upload', formData, {
header: {
'Content-Type': 'multipart/form-data'
}
})
const { fileName, filePath } = res.data
console.log('res.data', res.data)
setUploadedFile({ fileName, filePath })
console.log('setUploadedFile', fileName, filePath)
} catch (err) {
if (err.response.status === 500) {
console.log('There was a problem with the server')
} else {
console.log('msg No file uploaded', err.response.data.msg)
}
}
}
return (
<>
<form onSubmit={onSubmit}>
<div className='custom-file'>
<input
type='file'
name='file'
className='custom-file-input'
id='customFile'
onChange={onChange} />
<label
className='custom-file-label'
htmlFor='customFile'>{fileName}
</label>
</div>
<input
type='submit'
value='Upload file'
className='btn btn-secondary btn-block mt-4'
/>
</form>
{uploadedFile ? (
<div>
<h3>{uploadedFile.fileName}</h3>
<img scr={uploadedFile.filePath} alt='' />
</div>
) : null}
</>
)
}
export default FileUpload
The backend server is running on the port 5000(Assuming you haven't set the variable of process.env.PORT), therefore the url should be http://localhost:5000 or http://127.0.0.1:5000.
The axios.post('/upload', ...) is posting data to react url. Hence 404 error.
const res = await axios.post('http://localhost:5000/upload', formData, {
header: {
'Content-Type': 'multipart/form-data'
}
})