Upload multiple files using formidable and vue js - javascript

Hey guys i am trying to make an app in which i neeed to upload multiple files
but in my node backend when i try to upload files using postman it works
but while using with vue js it does not work
this is my node backend where i use formidable and try to upload images
app.post('/multiple', (req, res) => {
var form = new formidable.IncomingForm(),
files = [],
fields = [];
form.on('field', function (field, value) {
console.log('fields is', field);
fields.push([field, value]);
});
form.on('file', function (field, file) {
console.log('i came inside file');
console.log(file.name);
const oldPath = file.path;
const newPath = path.join(__dirname, 'uploads/' + file.name);
const rawData = fs.readFileSync(oldPath);
console.log('old path', oldPath);
fs.writeFileSync(newPath, rawData);
console.log('file uploaded');
console.log(JSON.stringify(field));
files.push([field, file]);
});
form.on('end', function () {
console.log('done');
});
form.parse(req);
console.log(files);
return res.json(files);
});
and this is my vue js front end component code
this is html code for vue js
<template>
<div>
<button #click="items++">Add One More File</button>
<form #submit.prevent="handleImageUpload">
<div v-for="item in items" :key="item">
<input type="file" #change="handleFile($event, item)" />
</div>
<input type="submit" />
</form>
</div>
</template>
and this is script tag for component
<script>
import axios from 'axios';
export default {
data() {
return {
items: 1,
files: [],
};
},
methods: {
async handleImageUpload() {
try {
const fd = new FormData();
this.files.map((index, file) => {
fd.append(index, file);
});
const { data } = await axios.post('http://localhost:5000/multiple', fd);
console.log('data from backend is ', data);
} catch (error) {
console.log(error);
}
},
handleFile(e, item) {
console.log(e);
this.files[item - 1] = e.target.files[0];
},
},
};
</script>
now what happend when I request backend with form data everything goes undefined there

ok so it was my mistake , I was writing map function the wrong way
it should be
this.files.map((file,index) => {

Related

Multiple image uploading using multer react JS and MySQL

I'm trying to make a upload image feature in my website. I've worked on uploading a single image and it worked how do I change my code to make it upload multiple images at same time code below:
Server Side:
// img storage confing
var imgconfig = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, "./uploads");
},
filename: (req, file, callback) => {
callback(null, `image-${Date.now()}.${file.originalname}`)
}
});
// img filter
const isImage = (req, file, callback) => {
if (file.mimetype.startsWith("image")) {
callback(null, true)
} else {
callback(null, Error("only image is allowd"))
}
}
var upload = multer({
storage: imgconfig,
fileFilter: isImage
})
// register userdata
app.post("/insertImage", upload.single("photo"), (req, res) => {
const { filename } = req.file;
console.log(req.file)
});
Client Side:
const [file, setFile] = useState("");
const setimgfile = (e) => {
setFile(e.target.files[0])
}
const addUserData = async (e) => {
e.preventDefault();
var formData = new FormData();
formData.append("photo", file)
const config = {
headers: {
"Content-Type": "multipart/form-data"
}
}
const res = await Axios.post("/insertImage", formData, config);
if (res.data.status == 201) {
console.log("NO error")
} else {
console.log("error")
}
}
REACT JSX
Here is my input file and multiple is added here
<div style={{ padding: 15, backgroundColor: '#fff', marginTop: 15 }}>
<h4>Upload file:</h4>
<input type="file" name='photo' onChange={setimgfile} multiple/>
<button onClick={addUserData}>submit</button>
</div>
Server code
app.post("/insertImages", upload.array("photos"), (req, res) => {
console.log(req.files)
});
Note: When uploading multiple images, Multer will populate req.files, and not req.file.
Client code
const formData = new FormData();
selectedImages.forEach((image, index) => {
formData.append(`photos[${index}]`, image)
})
<input type="file" name="photos" multiple>
Push all your files in your formdata using a loop, and the same thing to create the received files in disk.
dont forget to use multiple
<input type="file" id="fileInput" multiple />
for more details check this example https://www.freecodecamp.org/news/formdata-explained/

How To upload Sveltekit multiple files

In new svelteKit i cant upload multiple files with form multipart/form-data and multiple attribute
+page.svelte
<form
action="?/add"
method="post"
enctype="multipart/form-data"
>
<input
multiple
type="file"
name="file"
id="file"
accept="image/*"
/>
+page.server.js
export const actions = {
add: async ({ request, files }) => {
const data = await request.formData()
const file = data.get('file')
let filename
try {
if (file) {
const ext = file.name.split('.').pop()
filename = userName + '-' +Date.now().toString() + '.' + ext
let ab = await file.arrayBuffer()
console.log(Array.from(ab));
writeFileSync(`static/img/${filename}`, Buffer.from(ab, (e) => {
console.log(e)
}))
}
return { success: true }
} catch (e) {
console.log(e);
return { success: false };
}
}
}
This code upload only one file. How can I get an array of files?
There is a getAll function you can use if multiple values have been supplied for the same field name:
const data = await request.formData();
const files = data.getAll('file');

NodeJS-Reactjs File Upload Concurrent requests won't work

I am trying to build a project where Applicants can upload their CV and Images, These images and Resumes will be saved locally on the server, i am making two input components to select a file with a single upload button to make two axios requests to the nodejs server side to save the files in the required destinations when i make requests to upload both files only the first one will be saved while the other will be neglected
My Client side code for this part
import React from 'react';
import axios from 'axios';
import { useState, useEffect } from "react";
function FileUploads(props) {
const [file, setFile] = useState();
const [fileName, setFileName] = useState("");
const [image, setImage] = useState();
const [imageName, setImageName] = useState("");
const saveFile = (e) => {
setFile(e.target.files[0]);
setFileName(e.target.files[0].name);
console.log(e.target.files)
};
const saveImage = (e) => {
setImage(e.target.files[0]);
setImageName(e.target.files[0].name);
console.log(e.target.files)
};
const uploadFile = async (e) => {
console.log(file)
console.log(fileName)
console.log(image)
console.log(imageName)
const formData = new FormData();
formData.append("file", file);
formData.append("fileName", fileName);
const imageData = new FormData();
imageData.append("file", image);
imageData.append("fileName", imageName);
try {
const img = await axios.post(
"http://localhost:5000/uploadImage",imageData);
} catch (ex) {
console.log(ex);
}
try {
const img = await axios.post(
"http://localhost:5000/uploadCV",formData);
} catch (ex) {
console.log(ex);
}
};
return (
<body className="body">
<div className="containerMinimized" >
<div class="content">
<h2>Kindly Upload Your CV & Image</h2>
<h4 className='input-cv-text'>Upload your CV</h4>
<input className='input-cv' type="file" onChange={saveFile}/>
<h4 className='input-cv-text2'>Upload your Image</h4>
<input className='input-cv' type="file" onChange={saveImage}/>
<button className="checkButtonInput" onClick={uploadFile}>Upload</button>
</div>
</div>
</body>
);
}
export default FileUploads;
And here's my Endpoint using NodeJS
app.post("/uploadCV", (req, res) => {
const newpath = __dirname + "/applicantsResume/";
const file = req.files.file;
const filename = file.name;
console.log('')
file.mv(`${newpath}${filename}`, (err) => {
if (err) {
// res.status(500).send({ message: "File upload failed", code: 200 });
console.log(err)
}
// res.status(200).send({ message: "File Uploaded", code: 200 });
console.log('CV Uploaded Correctly')
});
});
app.post("/uploadImage", (req, res) => {
const newpath = __dirname + "/applicantsImages/";
const file = req.files.file;
const filename = file.name;
console.log('')
file.mv(`${newpath}${filename}`, (err) => {
if (err) {
// res.status(500).send({ message: "File upload failed", code: 200 });
console.log(err)
}
// res.status(200).send({ message: "File Uploaded", code: 200 });
console.log('Image Uploaded Succesfully')
});
});
I found a pattern sometimes when i restart the server it automatically inserts the missing file as if it was a pending request
Any ideas?

How to update files using Axios and React

I've built an api with posts/articles, and now I'm working on the front end. I'm having an issue with uploading a new photo for an already existing post. I've attempted the two most common methods for the photo, formData and JSON Base64. I'm receiving the same error response for both methods, Please upload a file, code: 400. I'm not certain where I've gone wrong, so I'll provide every relevant file.
articles.js(server)
exports.articlePhotoUpload = asyncHandler(async (req, res, next) => {
const article = await Article.findById(req.params.id);
if (!article) {
return next(
new ErrorResponse(`Article not found with id of ${ req.params.id }`, 404)
);
}
//Make sure user is article owner || make sure user is admin
if (article.user.toString() !== req.user.id || req.user.role !== 'admin') {
return next(
new ErrorResponse(
`User ${ req.user.id } is not authorized to update this article`,
)
)
}
if (!req.files) {
return next(new ErrorResponse(`Please upload a file`, 400))
}
const file = req.files.file;
// Confirm the image is a photo
if (!file.mimetype.startsWith('image')) {
return next(new ErrorResponse(`Please upload an image file`, 400))
}
// Check File Size
if (file.size > process.env.MAX_FILE_UPLOAD) {
return next(
new ErrorResponse(`Please upload an image less than ${ MAX_FILE_UPLOAD }`, 400)
)
}
// Create custom filename
file.name = `photo_${ article._id }${ path.parse(file.name).ext }`;
file.mv(`${ process.env.FILE_UPLOAD_PATH }/${ file.name }`, async err => {
if (err) {
console.log(err);
new ErrorResponse(`Problem with file upload`, 500);
}
await Article.findByIdAndUpdate(req.params.id, { photo: file.name });
res.status(200).json({
success: true,
data: file.name
});
});
});
^the above function is where the error message is triggered server-side.
axios.js(client-side)
...
axios.defaults.baseURL = 'http://<<ip address>>/api/v1';
axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('auth');
axios.defaults.headers.post['Content-Type'] = 'application/json';
export const uploadPhoto = (id, data) => {
return axios.put(`/articles/${ id }/photo`, {
data
})
}
...
^I have a feeling I could format this exported function better. I might be missing something here.
UploadPhoto.jsx(JSON Attempt)
const UploadPhoto = (props) => {
const { register, handleSubmit } = useForm();
const { state } = useStateMachine(updateAction);
const [file, setFile] = useState(null);
const [filename, setFilename] = useState(null);
const onSubmit = async () => {
const toBase64 = file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
console.log(reader.result)
});
const data = {
title: filename,
file: await toBase64(file),
}
uploadPhoto(`5ea5e73044718d0b2c2ae5df`, data)
.then(res => console.log(res))
.catch(err => console.log(err.response.data.error))
}
const handleChange = (e) => {
setFile(e.target.files[0]);
setFilename(e.target.files[0].name);
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<h2>Cover Image</h2>
<label>
Select A File:
</label>
<img id="image" src="" alt="" />
<input
type="file"
name="photo"
ref={register}
defaultValue={state.data.photo}
onChange={handleChange}
/>
<label htmlFor="">
Filename
</label>
<input type="submit" />
</form>
)
}
export default withRouter(UploadPhoto);
UploadPhoto.jsx(formData attempt)
const onSubmit = () => {
const formData = new FormData();
formData.append("file", file);
console.log(file)
uploadPhoto(`5ea5e73044718d0b2c2ae5df`, formData)
.then(res => console.log(res))
.catch(err => console.log(err.response.data.error))
}
This is my first time building my own api, which is why I put the server code in here. However, I'm 90% sure I'm making a mistake client-side, most likely in the axios.js file.
Let's try this example:
const fileUpload = require('express-fileupload');
const app = express();
// enable files upload -- this should also make 'req.files' accessible
app.use(fileUpload({
createParentPath: true
}));
Add this in the beginning of your server initialization. After that your normal code should try accessing req.files as it should be filled on file upload requests now.
You will need to install module express-fileupload before using it in code -> npm i express-fileupload
(Source: https://attacomsian.com/blog/uploading-files-nodejs-express)

react js handling file upload

I'm new to react js. I want to upload image asynchronously with react js
Suppose I have this code
var FormBox = React.createClass({
getInitialState: function () {
return {
photo: []
}
},
pressButton: function () {
var data = new FormData();
data.append("photo", this.state.photo);
// is this the correct way to get file data?
},
getPhoto: function (e) {
this.setState({
photo: e.target.files[0]
})
},
render: function () {
return (
<form action='.' enctype="multipart/form-data">
<input type='file' onChange={this.getPhoto}/>
<button onClick={this.pressButton}> Get it </button>
</form>
)
}
})
ReactDOM.render(<FormBox />, document.getElementById('root'))
Any answer will be appreciated!
You can make use of FileReader
var FormBox = React.createClass({
getInitialState: function () {
return {
file: '',
imagePreviewUrl: ''
}
},
pressButton: function () {
e.preventDefault();
// TODO: do something with -> this.state.file
console.log('handle uploading-', this.state.file);
},
getPhoto: function (e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
file: file,
imagePreviewUrl: reader.result
});
}
reader.readAsDataURL(file);
},
render: function () {
let {imagePreviewUrl} = this.state;
let imagePreview = null;
if (imagePreviewUrl) {
imagePreview = (<img src={imagePreviewUrl} />);
} else {
imagePreview = (<div className="previewText">Please select an Image for Preview</div>);
}
return (
<div>
<form action='.' enctype="multipart/form-data">
<input type='file' onChange={this.getPhoto}/>
<button onClick={this.pressButton}> Get it </button>
</form>
<div className="imgPreview">
{imagePreview}
</div>
</div>
)
}
})
ReactDOM.render(<FormBox />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="root"></div>
If you are planning to upload files using node and express then you have to create both server and client. The server has the api and the client is going to use that for uploading the file with axios.
Server part
First, we want to put in four packages that are express, explicit-fileupload,cors and nodemon. Run the below command to install applications.
npm i express express-fileupload cors nodemon
Now open the fileupload folder in your favorite code editor and create a brand new document referred to as server.js.
// server.js
const express = require('express');
const fileUpload = require('express-fileupload');
const cors = require('cors')
const app = express();
// middle ware
app.use(express.static('public')); //to access the files in public folder
app.use(cors()); // it enables all cors requests
app.use(fileUpload());
// file upload api
app.post('/upload', (req, res) => {
if (!req.files) {
return res.status(500).send({ msg: "file is not found" })
}
// accessing the file
const myFile = req.files.file;
// mv() method places the file inside public directory
myFile.mv(`${__dirname}/public/${myFile.name}`, function (err) {
if (err) {
console.log(err)
return res.status(500).send({ msg: "Error occured" });
}
// returing the response with file path and name
return res.send({name: myFile.name, path: `/${myFile.name}`});
});
})
app.listen(4500, () => {
console.log('server is running at port 4500');
})
use node server.js to start the server running.
Client
Open the react app folder on your favorite code editor and create a brand new report known as fileupload.js within the src folder. Now upload the following code.
// fileupload.js
import React, { useRef, useState } from 'react';
import axios from 'axios';
function FileUpload() {
const [file, setFile] = useState(''); // storing the uploaded file
// storing the recived file from backend
const [data, getFile] = useState({ name: "", path: "" });
const [progress, setProgess] = useState(0); // progess bar
const el = useRef(); // accesing input element
const handleChange = (e) => {
setProgess(0)
const file = e.target.files[0]; // accesing file
console.log(file);
setFile(file); // storing file
}
const uploadFile = () => {
const formData = new FormData();
formData.append('file', file); // appending file
axios.post('http://localhost:4500/upload', formData, {
onUploadProgress: (ProgressEvent) => {
let progress = Math.round(
ProgressEvent.loaded / ProgressEvent.total * 100) + '%';
setProgess(progress);
}
}).then(res => {
console.log(res);
getFile({ name: res.data.name,
path: 'http://localhost:4500' + res.data.path
})
}).catch(err => console.log(err))}
return (
<div>
<div className="file-upload">
<input type="file" ref={el} onChange={handleChange} />
<div className="progessBar" style={{ width: progress }}>
{progress}
</div>
<button onClick={uploadFile} className="upbutton">
Upload
</button>
<hr />
{/* displaying received video*/}
{data.path && <video src={data.path} autoPlay controls />}
</div>
</div>
);
}
export default FileUpload;
Now import the FileUpload component inside the App.js file.
// App.js
import React from 'react';
import FileUpload from './fileupload';
import './App.css';
function App() {
return (
<div className="App">
<FileUpload />
</div >
);
}
export default App;
Start the react app by running npm start.
For more: React File Upload Demo
import axios from 'axios';
var FormBox = React.createClass({
getInitialState: function () {
return {
photo: [],
name : '',
documents:[]
}
},
pressButton: function () {
var component = this
var data = new FormData();
data.append("photo", component.state.photo, component.state.name);
var request = axios.post('http://localhost:3000/document', data)
request.then(function(response){
// you need to send data from server in response
if(response.status == 200){
console.log('saved in db')
component.state.documents.push(response.data.documents)
// pushed document data in documents array
}
})
},
getPhoto: function () {
var uploadfile = document.getElementById(upload_doc).files[0]
this.setState({
photo: uploadfile, name : uploadfile.name
})
},
render: function () {
var documents = this.state.documents.map((doc)=>{
return <div>
<a href={doc.url}>{doc.name}</a>
<img src={doc.photo} />
</div>
})
// you can show your documents uploaded this way using map function
return (
<form action='.' enctype="multipart/form-data">
<input type='file' id='upload_doc' onChange={this.getPhoto}/>
<button onClick={this.pressButton}> Get it </button>
<span>{documents}</span>
// this way you can see uploaded documents
</form>
)
}
})
ReactDOM.render(<FormBox />, document.getElementById('root'))
One more easier way, by using using axios node module axios-fileupload
npm install --save axios-fileupload
const axiosFileupload = require('axios-fileupload');
axiosFileupload(url,file);
You can use React Dropzone Uploader, which gives you a dropzone that shows file previews (including image thumbnails) for dropped or chosen files, and also handles uploads for you.
import 'react-dropzone-uploader/dist/styles.css'
import Dropzone from 'react-dropzone-uploader'
const Uploader = () => {
return (
<Dropzone
getUploadParams={() => ({ url: 'https://httpbin.org/post' })} // specify upload params and url for your files
onChangeStatus={({ meta, file }, status) => { console.log(status, meta, file) }}
onSubmit={(files) => { console.log(files.map(f => f.meta)) }}
accept="image/*,audio/*,video/*"
/>
)
}
Uploads have progress indicators, and they can be cancelled or restarted. The UI is totally customizable, and the library has no dependencies.
Full disclosure: I wrote this library.
Use following module to select images.
https://www.npmjs.com/package/react-image-uploader
You can then upload image to server using xhr request. Following is the sample code.
var xhr = new XMLHttpRequest();
xhr.onload = function (e) {
//your success code goes here
}
var formData = new FormData();
xhr.open("POST", url, true);
formData.append('file', fileData);
xhr.send(formData);
You can use whatwg-fetch to make a post request. In your pressButton() function make the following changes -
import 'whatwg-fetch';
//....
pressButton: function (url) {
var data = new FormData();
data.append("photo", this.state.photo);
var options = {
body: data,
timeout: 3000 * 60 * 60
};
let callOptions = {
method : 'POST',
headers : {
'Content-Type': 'application/json'
},
body : JSON.stringify(options.body)
}
return fetch(url, callOptions).then(response => response.json());
}
Retrieve all the data in the form by using FormData then get all the inputs value and create a post request using axios with header 'content-type': 'multipart/form-data', that's how it works.
const CreateProfile = () => {
const handleFormSubmit = async (event) => {
event.preventDefault();
const form = new FormData(event.currentTarget);
const data = {
name: form.get('name'),
email: form.get('email'),
phone: form.get('phone'),
image: form.get('image'),
}
const response = await axios.post('https://example.com/api/create/profile',data,{ headers: {
'content-type': 'multipart/form-data'
}});
console.log(response);
}
return (
<div>
<form onSubmit={(event) => handleFormSubmit(event)} method="post">
<input type="text" name="name" required />
<input type="email" name="email" required />
<input type="tel" name="phone" required />
<input type="file" accept="image/jpg, image/png, image/webp" name="image" required />
<button type="submit">Submit</button>
</form>
</div>);
}

Categories