I'm using nodejs, REACT, express, axios. I want to make upload function, but I can't. When I upload file, server cannot parse the uploaded file (only shows {} log).
Below is my frontend code
When user click UPLOAD button on form element, 'handleSubmit' function is called, and 'handleSubmit' calls 'fileUploadRequest' function.
In 'fileUploadRequest' function, everything is good. I can see infomations of attached file.
<form onSubmit={this.handleSubmit} encType='multipart/form-data'>
<input type="file" onChange={this.handleChange}/>
<input type="submit" value="UPLOAD"/>
</form>
export function fileUploadRequest(username, uploadFile, uploadFileName) {
return (dispatch) => {
dispatch(fileUpload());
let formData = new FormData();
formData.append('fileName', uploadFileName);
formData.append('fileHandler', uploadFile);
return axios.post('/upload/upload', {formData})
.then((response) => {
dispatch(fileUploadSuccess());
}).catch((error) => {
dispatch(fileUploadFailure());
});
};
}
below is backend code.
router.post('/upload', (req, res) => {
console.log(req.body.);
var form = new formidable.IncomingForm();
form.parse(req, (err, fields, files) => {
console.log('parse');
console.log(fields);
console.log(files);
});
});
on req.body log, I can see only '{ formData: {} }' log.
'fields' and 'files' are all '{}' on log
How can I parse attached file on server?
Use multer for Express to handle the uploaded file.
Then use req.file to access all data about the uploaded file.
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
...
router.post('/upload', upload.single('fileHandler'), (req, res) => {
console.log('req.file.filename', req.file.filename); // the filename will be generated by multer
console.log('req.body.fileName', req.body.fileName); // to access the filename you created at the upload
});
#kadiks, thank you. I can parse uploaded file with multer.
but I found something more problem.
Even with multer, my code is not working.
below is not working code.
formData = new FormData();
formData.append('fileName', uploadFileName);
return axios.post('/upload/upload', {formData})
so i changed my code like this.
formData = new FormData();
formData.append('fileName', uploadFileName);
return axios.post('/upload/upload', formData);
only changed '{formData}' to 'formData', but this works good.
I don't know why this happens. someone else know this reason, please comment this issue.
Related
So I'm trying to make the html form:
<form action="blahblah" encblah="multipart/form-data" whatever>
Thats not the problem, I need to make that form send the blob to express
app.post('/upload/avatars', async (req, res) => {
const body = req.body;
console.log(req.file);
console.log(body);
res.send(body);
});
So I can access the blob, create a read stream, pipe it to the cloud, and bam, upload the file without downloading anything on the express server it self.
Is that possible?
If yes, please tell me how.
If no, please tell me other alternatives.
On the client we do a basic multi-part form upload. This example is setup for a single image but you could call uploadFile in sequence for each image.
//client.ts
const uploadFile = (file: File | Blob) => {
const formData = new FormData();
formData.append("image", file);
return fetch("/upload", {
method: "post",
body: formData,
});
};
const handleUpload = (event: any) => {
return event.target.files.length ? uploadFile(event.target.files[0]) : null;
};
On the server we can use multer to read the file without persisting it to disk.
//server.js
const express = require("express");
const app = express();
const multer = require("multer");
const upload = multer();
app.post(
"/upload",
upload.fields([{ name: "image", maxCount: 1 }]),
(req, res, next) => {
console.log("/upload", req.files);
if (req.files.image.length) {
const image = req.files.image[0]; // { buffer, originalname, size, ...}
// Pipe the image.buffer where you want.
res.send({ success: true, count: req.files.image.originalname });
} else {
res.send({ success: false, message: "No files sent." });
}
}
);
For larger uploads I recommend socket.io, but this method works for reasonably sized images.
it is possible, but when you have a lot of traffic it would overwhelm your express server (in case you are uploading videos or big files ) but if it's for uploading small images (profile image, etc...) you're fine. either way you can use Multer npm
I'd recommend using client-side uploading on ex: s3-bucket, etc..., which returned a link, and therefore using that link.
Looking for help on Uploading and Retrieving Images from MongoDb using multer.
My front end is ReactNative.(Not sure if this is needed but just to be sure.)
Multer
Problem: After looking and following tutorials i'm able to encode my path to base64 and upload it to my DB but now i'm confused how to retrieve the file from my DB. I saw some tutorials about decoding it from base64 but I don't quite understand how do I go about retrieving an image and displaying it in postman. (I tried looking but haven't found anything that gives me an answer. I'm sorry if this is a duplicated question. If you could point me in a direction or give me some advice I would be really greatful.)
**POST**
route.post("/sad", upload.single("image"), (req, res, next) => {
console.log(req.file);
const img = fs.readFileSync(req.file.path);
const img_enc = img.toString('base64');
const obj = {
usrImage: {
data: new Buffer.from(img_enc, 'base64'),
contentType: "image/jpg",
},
};
console.log(obj);
const newAccout = new account(obj);
newAccout.save();
});
**RETRIEVE**
route.get('/sad',(req,res)=>{
img.find({}).then((img)=>{
res.json(img)
//How do decode my buffer to show an image in Postman?
})
}
)
I am trying to create a userprofile where a username,password and image is saved. If you can help save an Image and then retrieve it from my accounts collection.
Hey I would advise that you start using a 3rd party for file upload like cloudinary very good way of managing files i.e images or video...
I am not that well of with multer but I can give a quick code example using Formidable does the same work as multer
Before you can start you'd need to make an account on cloudinary.com(don't worry its free)
Code below is how you could handle file upload
const Formidable = require("formidable"); //Meant for body parsing
const cloudinary = require("cloudinary").v2; // file uploader
//This below is your connection/configuration to get access to your cloudinary account so cloud_name, api_key and api_secret you'll get in your home dashboard(Cloudinary)
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.API_KEY,
api_secret: process.env.API_SECRET,
});
router.post('/api/file-upload', (req, res)=>{
const form = new Formidable.InconmingForm();
form.parse(req, (error, fields, files)=>{
const {file} = files
cloudinary.uploader.upload(file.path, {folder:"/"}, (err, res)=>{
const file_url = res.secure_url //This would be the url for your file given back by cloudinary
})
})
})
This script should upload your file and the file_url will be having the url of the file that you upload having ssl then after that you can now continue saving to mongoDB
Cloudinary docs for NodeJS
https://cloudinary.com/documentation/node_integration
Nice clear and understandable docs
Shameless plug
If you get lost you can check this video out on YouTube that I made handling file upload with cloudinary then save url given back to mongoDB
https://youtu.be/mlu-tbr2uUk
First call api find one
you will need fs module to complete following query
const fs = require('fs');
let data = await db.user.findOne({
where: {
id = req.body.id
}
})
// _________________ base 64 string data from findone query data
// |
let buff = new Buffer(data.image, 'base64');
let name = name.jpeg
let path = `tmp/${name}`; // <--- destination and file name you want to give to your file
fs.writeFileSync(path, buff);// < --this will write file to given path
fs.readFile(path, function (err, content) {// <------to send file in postman response
if (err) {
res.writeHead(400)
console.log(err);
res.end("No such image");
} else {
//specify the content type in the response will be an image
res.writeHead(200);
res.end(content);
}
});
fs.unlink(path, (err) => { // <-----to delete file from tmp directory
if (err) {
console.log(err)
}
})
Try this and switch to preview tab in postman.
I haven't tried it but maybe it helps.
route.get('/sad',(req,res)=>{
img.find({}).then((img)=>{
res.setHeader('contentType','image/jpg').send(img)
})
})
I am using Angular Material For getting Position of Draggable Image , getting input type file(pdf) from User and Images Stored in ./assets/emojis/. I am able to send Pdf from Angular to Node using ng2-file-upload and multer.
FrontEnd
<input (change)="onFileSelected()" ng2FileSelect [uploader]="uploader" type="file" id="file">
<ion-button class="input-group-text upload" (click)="uploader.uploadAll()" >Upload</ion-button>
Backend
app.post('/api/upload', upload.single('pdf'), function (req, res) {
console.log('File is available!');
return res.send({
success: true
})
});
Now i have image path selected by User at assets
imagePathToUpload:string = './assets/emojis/'+this.selectedEmoji
topPosition:number = this.topPos
leftPosition:number = this.leftPos
How can i send all these data together to Server , there is one way FormData but i dont understand how to use it.
Objective is Send Image , Pdf , left and top position to server. Any Advice would be Appreciated.
To send a file from Angular --> Nodejs is simple
Create upload method
FinalformData: FormData;
uploadFile(event) {
if (event.target.files && event.target.files.length > 0) {
const file = event.target.files[0];
this.FinalformData = new FormData();
this.FinalformData.append('file', file, file.name);
}
}
submit() {
// call your service and send it
this._sendfileService.sendFile(this.FinalformData)
.subscribe( res => {
if (res.success) {
console.log('file uploaded');
} else { console.log('faild uploading file'))}
})
}
all done now call your angular service with your http.post method here's and ex
sendFile(file: FormData): Observable<any> {
return this.http.post<any>(this.nodejsUrl, file);
}
to handle the file in backend look into multer https://www.npmjs.com/package/multer
I need to upload an image to a site and display it in the page after it's uploaded with a caption of the filename under the image. I've searched all over and found lots of tutorials about uploading and displaying on the same page, but I think that I just have a breakdown in my understanding of what goes into requesting info from a server and then displaying it back.
I'm writing my web app in node+react and using express and multer for the file IO. Here is my code:
import React from 'react';
import ReactDOM from 'react-dom';
import Dropzone from 'react-dropzone-component';
import fs from 'fs';
import express from 'express';
import mutler from 'mutler';
var app = express();
var storage;
var upload;
export default class Form extends React.Component {
constructor (props) {
super(props);
storage = multer.diskStorage({
//file destination
destination: function (req, file, callback) {
callback(null, '/uploads/');
},
//set the filename
filename: function (req, file, callback) {
callback(null, file.originalname);
this.state = {
name: file.originalname
};
}
});
upload = multer({ storage : storage}).single('userImage');
app.use('/uploads/', express.static(__dirname + '/uploads/'));
}
handleImageUpload () {
app.post('/', function (req, res) {
fs.readFile(req.files.userImage.path, function(err, data) {
console.log('error with ' + data);
});
upload(req, res, function (err) {
if (err) {
return res.end("Error uploading file.");
}
res.writeFile("/uploads/" + origName, new Buffer(req.body.photo, "base64"), function(err) {
console.log("error writing image");
});
res.redirect('/');
});
});
}
getName () {
return this.state.name;
}
render () {
return (<div>
<form action="/" method="post" enctype="multipart/form-data">
<input type="image" name="userImage"/>
<input type="submit" name="submit" value="submit" onClick={this.handleImageUpload.bind(this)}/>
</form>
</div>
);
}
}
I've tried following multiple tutorials (which is why Dropzone is imported) but I just can't figure this out for what I want to do.
I figured that if I save the filename to state in the constructor, that then I can get it later and display it in another file, which is simply attributing the file's url to an image source in a higher up react file.
My question is this: where have I gone wrong? By my reasoning this should work, but I'm new to file IO with node and what seems to be common knowledge to a lot of people in the tutorials that I've read just isn't clicking with me. Thank you in advance for your help!
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);
I am assuming that you are implementing following requirement.
Allow user to select image.
Upload selected image
Show selected image to user.
What my solution will help
Allow user to select image
Show user what he/she selected.
Upload image to server by available callback(mentioned in tutorial)
Show success or failure.
If you need any help do let me know. :)
I also use Mongoose, if that is relevant. I am trying to allow users to upload a profile picture. There must be a simple way, isn't there?
I think you should try multer.
Simple from multer site:
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
app.post('/upload', uploads.any(), function(req,res){
res.send(req.files);
});
It should upload file in your uploads folder (under root), and return file in JSON.
In this example you will see how to store the file you are sending in to your server directory and then pick them up from there and save them. You can also directly save them. First you pick up the file using angular, you can use anything, if you want you can check here for more details. Here is my small example the code is in jade.
<input type="file" name="file" onchange="angular.element(this).scope().selectFile(this.files)"/>
<button ng-click="savePhoto()">Save </button>
In your angular controller
$scope.savePhoto = function () {
var fd = new FormData();
fd.append("file", $scope.files[0]);
)) ;
$http.post("/xxx/photos", fd, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (data) {
$scope.image = data; // If you want to render the image after successfully uploading in your db
});
};
Install multer using npm in your back end. And then in app.js you can set up a middleware to collect the files you are sending in. Just do console.log(req) here to check if you are getting the files till here. Multer does the magic here.
app.use(multer({
dest: path.join(__dirname, 'public/assets/img/profile'),
rename: function (fieldname, filename, req, res) {
console.log(req)// you will see your image url etc.
if(req.session.user) return req.session.user.id;
}
}));
So here the image will be stored in this path (public/assets/img/profile) in your server. Now you pick up the file from this server and add to your db.
var path = require('path');
var imgPath =path.join(__dirname, '../public/assets/img/profile/' + id + '.jpg'); // this is the path to your server where multer already has stored your image
console.log(imgPath);
var a ;
a = fs.readFileSync(imgPath);
YourSchema.findByIdAndUpdate( id, {
$set:
{'img.data' : a,
'img.contentType' : 'image/png' }
}, function(err, doc) {
if (err)console.log("oi");
}
);
//In case you want to send back the stored image from the db.
yourSchema.findById(id, function (err, doc) {
if (err)console.log(err);
var base64 = doc.img.data.toString('base64');
res.send('data:'+doc.img.contentType+';base64,' + base64);
});