I'm writing an application that accepts uploads from a client to server using electron, node and multer.
What I wanna do is only allow the upload after the server has accepted it. Maybe some kind of prompt. How would I go about it in JS?
Even though I mentioned multer, I imagine it's not gonna play a big part in this. Rn, my upload function goes through like this.
var upload = multer({ storage: storage, })
app.post('/uploadfile', upload.single('single'), (req, res, next) => {
const file = req.file
if (!file) {
const error = new Error('Please upload a file')
error.httpStatusCode = 400
return next(error)
}
res.send(file)
})
When the request comes, instead of running "upload.single", I imagine I have to use something else that prompts for validation and then run the actual upload function. But I'm very clueless. Any help is appreciated.
Related
I have multer as middleware before editing user function. The thing is that multer uploads photo no matter what, so I am wondering if there is a way to somehow cancel upload if e.g. email is invalid. I tried to delete uploaded image through function via fs.unlink if there is validation error within edit function, but I get "EBUSY: resource busy or locked, unlink" error. I guess that multer uploads at the same time while I try to delete image.
Any ideas how to solve this?
on your function make a try/catch block and handle on error throw
import { unlink } from 'node:fs/promises';
import path from 'path'
// code ...
// inside your function
const img = req.file // this needs to be outside the try block
try {
// your code, throw on failed validation
} catch (e) {
if (img) {
// depends on where you store in multer middleware
const img_path = path.resolve(YOUR_PATH, img.filename)
await unlink(img_path);
console.log(`deleted uploaded ${ img_path }`);
}
// revert transaction or anything else
}
Nowadays, applications usually separates uploading file API from data manipulating API for some features like previewing/editing image. Later, they can run a background job to clean unused data.
But if it's necessary in your case, we can use multer's builtin MemoryStorage to keep file data in memory first, then save it to disk after validation completes.
const express = require('express');
const app = express();
const multer = require('multer');
const storage = multer.memoryStorage();
const upload = multer({ storage });
const fs = require('fs');
app.post("/create_user_with_image", upload.single('img'), (req, res) => {
// Validation here
fs.writeFile(`uploads/${req.file.originalname}`, req.file.buffer, () => {
res.send('ok');
});
});
Note: as multer documentation said, this solution can cause your application to run out of memory when uploading very large files, or relatively small files in large numbers very quickly.
I am trying to design a simple app in NodeJS that uploads a CSV file via an HTML form.
Having carefully followed this tutorial on YouTube on how to upload files using NodeJS, I don't understand why my code isn't able to upload any file. I haven't gotten further than 6:53 mins in the youtube tutorial.
Find below my simple code:
const express = require('express');
const app = express();
const multer = require('multer');
const fileStorageEngine = multer.diskStorage({
destination: (req,file,cd)=> {
cd(null, './uploads')
},
filename: (req,file,cb)=>{
cb(null, Date.now() + '--' + file.originalname);
},
});
const upload = multer({storage: 'fileStorageEngine'});
app.get('/', (req,res)=> {
res.sendFile(__dirname +'/testDir/form.html' );
});
app.post('/uploads', upload.single('file'), (req, res)=> {
console.log(req.file);
res.send('Single File Upload Success!');
});
app.listen('3600', ()=> console.log('App is listening...'));
...and my HTML form code looks like this:
http://localhost:3600/ correctly displays
I am able to browse to whatever file I choose, and clicking on the submit button that gets me directed to:
According to the YouTube at 6:53 mins, the uploads folder should now contain the uploaded file,
however, the folder is empty!
Also, the terminal displays
...suggesting that console.log(req.file); no file was actually read in.
I also tried using postman and this is a screenshot of the result:
I have tried to re-watching the video and carefully followed the instructions but still haven't been able to resolve the issue.
Kindly help me understand why the upload isn't working and how to resolve this issue.
Looking forward to your help.
You have set the storage field as a string instead of a multer.diskStorage object.
Change it to: const upload = multer({storage: fileStorageEngine});
Also make sure that the key value in Postman form-data is set to file, because you are using upload.single('file')
Make sure you have enctype="multipart/form-data" in your html form. Also, make sure you have set name correctly. Can you paste the code for your form as well?
Working with multer and gridFS for an express API I am developing. I am having trouble moving the upload object to another file. I have setup multer so that
export const upload = multer({
storage,
});
The following code works in index.ts where multer is initiated but not in any other routes file.
router.post("/upload", single("image"), (req, res) => {
const file = req.file;
if (!file) {
const error = new Error("Please upload a file");
res.send(error);
}
res.send(file);
});
It's not possible for me to post a whole snippet but I hope this is enough.
Cheers
I was actually able to solve this by adding the following:
app.use(
multer({
storage,
}).single("image")
);
Now that might mean it will run for every route which is another issue to address
you can do like this:
for all path
app.use('*', multer({storage}).single("images"));
just for post request
app.post('*',multer({storage}).single("images"))
For all post routes but a few routes
app.post('*',(req,res,next)=>{
const exceptionPaths = ["singup","login"]//don't upload
if(exceptionPaths.includes(req.path))return next()
next()
},multer({storage}).single("images"))
I have 2 nodeJS services and I would want to upload file in a dir, from one NodeJS (backend) to another NodeJS(backend). The receiver nodeJS is an express app.
Looking for some working code sample.
PS: Couldn't find any code samples in search, since everywhere it was Multer from client to server uploads that receives multipart/form-data.
Uploading file using POST request in Node.js
Receive the file first as you correctly said using Multer. Then, you may either save the file to a temporary directory before uploading it again or just send the file as-is.
You need to setup a server running with Multer on the 2nd server that wishes to receive the file.
const express = require('express');
const app = express();
const upload = multer({ dest: 'files/' });
app.post('/upload', upload.single('file'), (req, res) => {
res.sendStatus(200);
});
app.listen(3001);
Then on the server you wish to send the file from, do something like this:
const request = require('request');
const req = request.post('localhost:3001/upload', (err, res, body) => {
if (err) throw new Error(err);
if (res && res.statusCode == 200) {
console.log('Success');
} else {
console.log('Error');
};
});
const form = req.form();
form.append('file', fs.createReadStream('./location/to/file'));
I have a Node server using express.
I was originally using body-parser, but that doesn't allow for file uploads. So, I switched to multer (the easiest integration with express). However, in order to get any of the req (specifically req.body), this is my code:
var multer = require('multer');
var upload = multer({ dest : 'uploads/' });
server.all('/example', function (req, res, next) {
var up = upload.single('photo')
up(req, res, function(err) {
console.log(req.body); // I can finally access req.body
});
}
The problem with this, is that not all of my routes need to upload a file. Do I need to waste the CPU on calling upload.single() for each route in order to get access to the body? upload.single('') ends up not uploading any file, but it's still precious time spent on the main thread.
It appears that upload.single() waits for the callback, so it may not be as big of a deal as I'm making it, but I don't like calling functions when I don't have to.
Is there a way around calling upload.single(), or am I just making a bigger deal out of this than it really is?
For text-only multipart forms, you could use any of the multer methods, which are .single(), .array(), fields()
For instance using .array()
var multer = require('multer');
var upload = multer({ dest : 'uploads/' });
server.all('/example', upload.array(), function (req, res, next) {
console.log(req.body);
});
It doesn't really matter which you use, as long as it's invoked without arguments Multer will only parse the text-fields of the form for you, no files