How to download files using multer-sftp - javascript

I have this code, but surfing the web, i cannot found some way to download a file from the remote server. I'm able to upload the files in the remote server but I don't have any idea how download from there.
var storage = sftpStorage({
sftp: {
host: '171.16.....',
port: xxxx,
username: 'username',
password: 'xxxxxxxxxxxxxxxx'
},
destination: function(req, file, cb) {
cb(null, 'uploads')
},
filename: function(req, file, cb) {
cb(null, Date.now() + file.originalname)
}
});
var upload = multer({ storage: storage })
This is the route to upload the files: (Works great!)
router.post('/upload-image', upload.single('file'), listarController.uploadImage);
This is the route to download the files - locally: (Searching a method...)
router.get('/get-file/:file', listarController.getFile);
The method to download locally:
controller.getFile = (req, res) => {
var file = req.params.file;
var path_file = './uploads/' + file;
fs.exists(path_file, (exists) => {
if (exists) {
return res.sendFile(path.resolve(path_file))
} else {
return res.status(200).send({
message: "The image doesn't exist."
})
}
})
}
Some suggestion? Thanks in advance

I solved it with the following libraries:
1. multer-sftp: To upload the files.
2. ftp: To download and rename the files.

Related

Docker and Multer upload volumes ENOENT error

first question + junior dev here !
So my problem is : I'm developping an API whith nodejs/express + Docker and Multer where I want to upload files.
I tried to configure Docker as good as I can, same for Multer and persist uploaded files in a volume but it keeps throwing me this error :
{
"errno": -13,
"code": "EACCES",
"syscall": "open",
"path": "public/media/pictures/picture-1642414319690.jpg",
"storageErrors": []
}
Here is my Multer upload middleware config :
const multer = require('multer');
const path = require('path');
// PICTURES
// Picture storage path
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, '/public/media/pictures');
},
filename: (req, file, cb) => {
cb(
null,
`${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`
);
},
});
// Check pictures type
const checkPicType = (file, cb) => {
// Allowed ext
const pictypes = /jpeg|jpg|png/;
// Check ext
const extname = pictypes.test(path.extname(file.originalname).toLowerCase());
// Check mime
const mimetype = pictypes.test(file.mimetype);
if (mimetype && extname) {
return cb(null, true);
}
return cb('Error: Images only!');
};
// Picture upload options
const picUpload = multer({
storage,
limits: {
fields: 5,
fieldNameSize: 10,
fieldSize: 2000,
fileSize: 25000000,
},
fileFilter(req, file, cb) {
checkPicType(file, cb);
},
}).single('picture');
module.exports = {
picUpload,
};
My Upload method in api/picture.js :
router.post('/upload', (req, res) => {
picUpload(req, res, (err) => {
if (err) {
return res.status(403).json(err);
}
return res.status(201).json({
path: `${req.protocol}://${req.hostname}:${PORT}/${req.file.path}`,
});
});
});
and finally my docker-compose :
services:
web:
build:
context: ./
target: dev
volumes:
- .:/src
- uploaded-files:/src/public/media/files
- uploaded-pictures:/src/public/media/pictures
command: npm run start:dev
ports:
- "5000:5000"
environment:
NODE_ENV: development
DEBUG: nodejs-docker-express:*
postgres:
image: postgres
restart: always
environment:
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASS}
volumes:
- postgres:/var/lib/postgresql/data
ports:
- '5432:5432'
volumes:
postgres:
uploaded-files:
uploaded-pictures:
As I said I'm pretty to docker and multer so if I missed a file or some lines to help you understand better, tell me.
Thanks!
I figured it out, it was just a simple path arror in the middleware (picUpload.js)
cb(null, '/src/public/media/pictures');
// Picture storage path
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, '/src/public/media/pictures');
},
filename: (req, file, cb) => {
cb(
null,
`${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`
);
},
});

can't change name to uploaded file using multer

I am trying to change the name of the image im uploading to the server using multer which gives the file a random name.
I user multer.diskStorage method to do so as described in the documentation but it keeps saving the file with random names
CODE:
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null,'./uploads/')
},
fileName: (req,file,cb) => {
cb(null, file.originalname)
}
})
const upload = multer({storage: storage})
router.post('/', upload.single('carImage') ,(req, res) => {
res.send(req.file);
}
RESPONSE :
{
fieldname: 'carImage',
originalname: 'testOCR8.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: './uploads/',
filename: '229f70c20e5550dbe638db49791ef17d',
path: 'uploads/229f70c20e5550dbe638db49791ef17d',
size: 1712380
}
im uploading to the server using multer which gives the file a random name
You made a typo. It is filename not fileName. This is the standard behavior as per the docs.
filename is used to determine what the file should be named inside the folder. If no filename is given, each file will be given a random name that doesn't include any file extension.
So, your code should be
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null,'./uploads/')
},
filename: (req,file,cb) => { // notice the change 'filename'
cb(null, file.originalname)
}
});
const upload = multer({storage: storage});
Try a different approach for using StorageMulter. Try the following -
var StorageMulter = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, "./temp");
},
filename: function(req, file, callback) {
var uploadFileName = "x.jpg"; //Manipulate this variable accordingly
callback(null, uploadFileName);
}
});
var upload = multer({
storage: StorageMulter
});
app.post("/api/uploaddocument", function(req, res) {
upload(req, res, function(err) {
if (err) {
return res.end("Something went wrong!"+ err);
}
});
});

Multer trying to create a new folder when one already exists

I'm using Multer to manage image uploads, and when running my app on my local machine everything works perfectly. But now that I'm trying to deploy to Heroku I get this error in my application logs:
Unhandled rejection Error: EROFS: read-only file system, mkdir
'/public'
...which seems like it's trying to create a directory rather than using the existing one (like it does on my local machine)
This is my the code I'm using for Multer:
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'public/img/') },
filename: (req, file, cb) => {
cb(null, new Date().toISOString() + file.originalname)
} })
var upload = multer({storage: storage})
router.post('/:propertyid', upload.single('img'), function(req, res) {
Property.update({
img: req.file.filename
}, {
where: {
id: req.params.propertyid,
}
}).then(updatedProperty => {
res.redirect('/admin/' + updatedProperty)
})
});
The public/img directory already exists and when testing it, it runs fine with correct filenames and end up in the correct place. Any help is appreciated! Thanks!
Heroku dynos have an ephemeral filesystem. This answer by Naaman Newbold, explains very well what that means.
TL;DR:
Dynos' filesystem shouldn't be used to store any permanent storage or data besides what is deployed. In order to do use a storage, AWS S3 can be used.
You can Use fs-extra to create folder it will sync and create folder like below in below code I am creating directory by user_id and uploading multiple images so i have used fs.mkdirsSync(path) in my code
let fs = require('fs-extra');
let storage = multer.diskStorage({
destination: function (req, file, cb) {
let Id = req.body.id;
let path = `tmp/daily_gasoline_report/${Id}`;
fs.mkdirsSync(path);
cb(null, path);
},
filename: function (req, file, cb) {
// console.log(file);
let extArray = file.mimetype.split("/");
let extension = extArray[extArray.length - 1];
cb(null, file.fieldname + '-' + Date.now() + "." + extension);
}
})

Encrypt the uploaded file before saving to disk using Node.js

Currently, I am using multer library to save files on File system. This application is using Node and Express.
I can save the file first on server and then encrypt it. Later on delete the unencrypted file. However, I do not want to add unencrypted file on server directly. So, I am looking for a way to encrypt the incoming file from the front end and then save it to disk.
const defaultFolder = 'upload';
const filePath = resolveHome(process.env.FILE_STORAGE_LOCATION || defaultFolder);
const key = 'test';
const cipher = crypto.createCipher('aes-256-cbc', key);
const decipher = crypto.createDecipher('aes-256-cbc', key);
const upload = multer({
storage: multer.diskStorage({
destination: filePath,
filename: (req, file, cb) => {
const parts = file.originalname.split('.');
const ext = parts.pop();
const name = parts.join('.');
cb(null, name + '-' + Date.now() + '.' + ext);
},
}),
}).single('file');
app.post('/upload', (req, res) => {
upload(req, res, err => {
if (err) {
return res.status(400).send({
error: 'The request was invalid',
fileName: req.file.originalname,
});
}
return res.status(200).send({
fileName: req.file.filename,
});
});
});
I tried to use crypto library to encrypt the file but it's not working. I believe the req.cipher is invalid as I would normally use req.file to get reference to the file.
app.post('/upload', (req, res) => {
upload(req, res, err => {
output = fs.createWriteStream(filePath + '/' + req.file.originalname);
req.pipe(cipher).pipe(output).on('finish', () => console.log('Encrypted file written on disk'));
if (err) {
return res.status(400).send({
error: 'The request was invalid',
fileName: req.file.originalname,
});
}
return res.status(200).send({
fileName: req.file.originalname,
});
});
});
I had tried to just write file without using cipher and file was empty. Adding this information in case it helps.
req.pipe(output).on('finish', () => console.log('Encrypted file written on disk'));
Can you try this
app.post('/upload', function(req, res) {
upload(req, res, function(err) {
var fileName = req.file.destination +"\\"+ req.file.filename
var input = fs.createReadStream(fileName);
var output = fs.createWriteStream(fileName + ".enc");
input.pipe(cipher).pipe(output);
output.on('finish', function() {
fs.unlink(fileName, (err) => {
if (err) throw err;
console.log('Encrypted file written to disk!');
res.end('Encrypted file written to disk!')
});
});
})
})

Rename file using multer-ftp

I am trying to upload a file to an ftp using multer-ftp. It successfully uploads to the ftp however I need to change the name of the file. Is there a way to do this?
var upload = multer({
storage: new FTPStorage({
basepath: '/path',
ftp: {
host: host,
secure: false,
user: user,
password: pwd
}
})
}).single('fileupload');
app.post('/getfiles', function (req, res, next) {
upload(req,res, function(err){
if(err){
res.send('Error uploading file - ' + err);
}else{
res.send('File is uploaded - ' + JSON.stringify(req.file));
}
})
})
In req.file it has the original file name as it was uploaded. How can I get multer-ftp to upload the file using that name instead of the name it is coming out as (example format it is coming out as is 5acfbabc8430fb3d311ae365f448.png
Check this code, use destination option to rename the file.
var upload = multer({
storage: new FTPStorage({
basepath: '/path',
destination: function (req, file, options, callback) {
callback(null, path.join(options.basepath, file.originalname))
},
ftp: {
host: host,
secure: false,
user: user,
password: pwd
}
})
}).single('fileupload');
//corrected code

Categories

Resources