Upload Images to Web Server directory using Multer [Nodejs] - node.js

I am upload images using multer and Nodejs. The upload works perfectly. The problem is I want to upload those images directly to a folder inside wwwroot folder of the IIS Webserver.
var Storage = multer.diskStorage({
destination: function (req, file, callback) {
// callback(null, "../grit-server/uploads/");
callback(null, "https://example.com/grit/images/photogallery/");
},
filename: function (req, file, callback) {
const sqc = sqlConn;
var fileNames = (file.originalname.split('_'))
let query = 'INSERT INTO dbo.MS_PhotoGallery (MinorId,Photo_Name) VALUES (#MinorId,#PhotoName)'
let params = [
sqc.paramize('MinorId', fileNames[1], sql.Int()),
sqc.paramize('PhotoName',fileNames[2], sql.VarChar(255))
]
sqc.SqlExecuteStatementCallback(
query,params,(result)=>{
res.send(result)
}
)
callback(null, file.originalname);
}
});
The above code is of the Multer storage where I am setting the URL where to upload the images. But it is throwing error
'Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client'
What modifications shall I do to upload the images in the URL mentioned under Storage to save any photos in the location.

I have solved this problem hardcoding the path like '../../../../wwwroot/abc/def/'. This is not the efficient way but it works for my specific problem as the images folder is not going to change in future.

Related

Heroku | Cannot GET

I deployed an API to heroku. One of its functions is file uploading. I made a static folder called "uploads" and upload files using multer package.
app.use('/api/uploads', uploadRouter);
app.use('/uploads', express.static(path.join(__dirname, '/uploads')));
Above code snippet comes from server.js. Below is the router and multer setup.
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, 'uploads/');
},
filename(req, file, cb) {
cb(null, `${Date.now()}.jpg`);
},
});
const upload = multer({ storage });
uploadRouter.post('/', upload.single('image'), (req, res) => {
res.send(`https://app.herokuapp.com/${req.file.path}`);
});
uploadRouter.post('/imgs', upload.array('images'), (req, res) => {
try{
let filesArray = [];
req.files.forEach(file => {
filesArray.push(`https://app.herokuapp.com/${file.path}`)
})
res.status(201).send(filesArray);
}catch(error) {
res.status(400).send(error.message);
}
});
Something tells me that my approach is far from an ideal one. However, it used to work just perfect until I introduced multiple file upload. Now, images after being uploaded stay there for a little bit (I can access them via links like https://app.herokuapp.com/uploads/1623782012131.jpg) and disappear over few minutes. Then, these URLs throw the following:
Cannot GET /uploads/1623782012131.jpg
The thing is that my previous images that I uploaded before introducing multiple file upload are still accessible. I thought it had to do with heroku file size limitations but it was not the case since I've only used about 50mb out of 500mb. What might be the reason?
Heroku's filesystem is ephemeral/short lived. This means that any images you save on the disk will disappear after you restart or deploy your app. You can't rely on Heroku's filesystem to store images that need to persist for a longer time. Read more here: https://help.heroku.com/K1PPS2WM/why-are-my-file-uploads-missing-deleted
For a reliable image storage, have a look at cloud storage solutions such as Cloudinary or AWS S3.

Why am I NOT able to upload files with the following NodeJS code?

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?

How to upload images to GCS bucket with multer and NodeJS?

I'm facing issues for uploading local images to my google cloud storage.
I've already tried two methods. The first one is uploading with multer
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './uploads/')
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now())
}
});
var upload = multer({storage: storage}).single('image');
app.post('/upload',function(req,res,next){
upload(req,res,(err) => {
if(err){
console.log(err)
}else{
console.log(req.file)
}
})
})
Then, i've tried directly with GCS
var bucket = admin.storage().bucket('mybucket')
app.post('/upload',function(req,res,next){
bucket
.save(file)
.then(() => {
})
for both of these solutions , req.files is always undefined whereas req.body is a buffer like this :
<Buffer 2d 2d 2d 2d ...>
when i try to save this buffer on my GCS bucket, i the .jpg/png file is created in my bucket but it is corrupted.
I'm browsing the web seeking for a solution but i found nothing that helped me to overcome this situation.
Any advice ?
You need multer, multer-google-storage and ofcourse bodyParser if you have additional form values. You need to sent data in multipart/form-data
In your .env file
GCS_BUCKET = <bucket name>
GCLOUD_PROJECT = <project id>
GCS_KEYFILE = <key file location>
You can download key file from GCP Console>Your Project>I AM & Admin>Service Accounts
In your route
const multer = require('multer');
const multerGoogleStorage = require("multer-google-storage");
var uploadHandler = multer({
storage: multerGoogleStorage.storageEngine()
});
router.post('/', uploadHandler.single('image'), function (req, res, next) {
const body = req.body;
res.json({fileName: req.file.filename});
res.end();
}
This will store file on to GCS with name [random-string-generated-by-gcs]_[YOUR FILE NAME WITH EXTENTION]. The same can be access under the route via req.file.filename.
Documentation
Make sure you have added enctype="multipart/form-data" attribute to your form. A probable reason for req.files being undefined.

Node js store images into external server

I am developing one web application in which server is stored in different Azure server and front-end is also stored in different one.
When I try to use multer in node js to store URL to front-end server it always returns that path is not found.when I saw the error log it I found this
Error: ENOENT: no such file or directory, open
'D:\home\site\wwwroot\http:\nomadiccare-portal.azurewebsites.net\images\undefined.png'
at Error (native)
Here is my source code for node js which is working perfectly on localhost.
var uploadImageURL="http://nomadiccare-portal.azurewebsites.net/images/";
var currentClientId;
var storage = multer.diskStorage({
destination: function (request, file, callback) {
callback(null, uploadImageURL);
},
filename: function (request, file, callback){
console.log("It Is In"+file);
callback(null,currentClientId+".png");
}
});
var upload = multer({ storage: storage });
How can I remove D:\home\site\wwwroot\ from URL?
destination of DiskStorage is used to determine within which folder the uploaded files should be stored. It must be the path of the disk rather than a URL of the website.
If the other server has a post route to upload a file, you can make a post request with the file data from your server after you saved the file successfully. Refer to this you can learn how to send HTTP post request from a server to another server with data in Node.js.
var storage = multer.diskStorage({
destination: uploadImageURL, // change here
filename: function (request, file, callback) {
console.log('It Is In' + file)
callback(null, currentClientId + '.png')
}
})

Using Multer and Express to upload and display files

I'm using multer to upload images with express and node from a form, however all the files names come out like "8f92a1388f70c6c88eb32489f6bcfcc9". There isn't even an extension attached. How to I display this on the client side?
try:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/where/ever/the/upload/dir/is')
},
filename: function (req, file, cb) {
cb(null, file.orignalname)
}
})
var upload = multer({ storage: storage })
Instead of:
var upload = multer({ dest: 'uploads/' })
Requesting the file:
With the proper permissions set on the file/or directory your server should be able to request it fine, remember to explicitly write the file name with an extension if you aren't doing anything fancy after the file is written ;)
If you want more control over your uploads, you'll want to use the
storage option instead of dest. Multer ships with storage engines
DiskStorage and MemoryStorage; More engines are available from third
parties.
--The Horse
(ref: github: expressjs/multer)
Note: Multer will not append any file extension for you, your function should return a filename complete with an file extension

Resources