I'm allowing users to upload files and would like to know if it is possible to only allow the user who uploaded their files access to it.
Currently I am just uploading these to a static folder (Public).
Simply put a route to render the file (this will decrease performance)
Save the file as : filename.extension.userid in a non public folder for example a directory named upload.
Put a route to catch the request on the directory upload :
app.get("/upload/:filename", function(req, res){
var fname = req.params.filename;
var userid = req.user.id; // RETRIEVE AUTHENTICATED USER ID
var fullname = fname+"."+userid;
fs.readFile(__dirname+"/../public/upload/"+fullname, 'base64', function(err, data){
if(err || !data) return res.status(404);
res.set('Content-Disposition', 'attachment; filename="'+fname+'"');
res.set('Content-Type', 'application/pdf'); // example for pdf
return res.end(data, 'base64');
});
});
I couldn't find a reason why you were suggesting using another route to handle the upload. I was able to post to the same route. All that I needed to do was include the path and set it accordingly.
var folder = newPath = path.join(__dirname, '..', './uploads')
var newPath = folder + '/' + callback.fileName;
fs.writeFile(newPath, data, function(err) {
if (err) {
console.log(err)
} else {
//Do stuff
}
});
After the file was uploaded I was then able to complete my task.
Related
I have Express API which used to upload file to the files directory. Whenever I call my API res.send redirecting to a new page. How can I perform this API with reloading my current page?
app.post('/upload', function(req, res) {
let sampleFile;
let uploadPath;
if (Object.keys(req.files).length == 0) {
res.status(400).send('No files were uploaded.');
return;
}
console.log('req.files >>>', req.files); // eslint-disable-line
sampleFile = req.files.sampleFile;
console.log('lusu', sampleFile); // eslint-disable-line
uploadPath = __dirname + '/uploads/' + sampleFile.name;
sampleFile.mv(uploadPath, function(err) {
if (err) {
return res.status(500).send(err);
}
res.send('File uploaded to ' + uploadPath);
});
});
First of all, I would like to recommend multer package for file upload in node js.
instead of res.send(), try res.status(200).json({message:"successfully uploaded"})
try debugging at front end, suppose you have a function for file upload like below,
function fileUpload(){
http.post('url',{headers:headers}).then(res){
// Try to handle the response here. Do not write anything that reloads the page.
}
}
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);
});
How can I create a folder (if the folder does not exist yet) before the image will be uploaded? I always get error ENOENT.
When I try this code:
module.exports = function(router){
router.post('/result', directory.tmp, uploader.single, function(req,res){
//some data manipulation here
});
}
//directory.js
module.exports.tmp = function(req, res, next){
mkdirp('./tmp/' + moment().format('MM-DD-YY') + '/' + moment().format('HH'), function (err) {
if (err) console.error(err)
console.log("==================================");
console.log("tmp folder created");
console.log("==================================");
});
next();
};
Though I used directory.tmp first so it will create a folder if it is not existing, I think uploader.single is executed first that is why I got that error. After receiving the error, then that's the time my app created the folder. So in other words, the file uploaded was not saved. How to fix this so it will create the folder first, then upload the file. Btw, I am using mkdirp and multer.
I would suggest you to do the next(); inside the callback of mkdirp.
Because like you did, why it creates the folder it calls next and goes further and the folder is not yet created. This is why you should wait for folder creation first.
module.exports.tmp = function(req, res, next){
mkdirp('./tmp/' + moment().format('MM-DD-YY') + '/' + moment().format('HH'), function (err) {
if (err) console.error(err)
console.log("==================================");
console.log("tmp folder created");
console.log("==================================");
next();
});
};
I'm trying to find an answer to this question for a long time: I need to upload a text/html file through my Node.Js express app and to save its contents into a variable for further treatment.
I can make the multipart form, of course, and post the content, but what I can access so far is only req.files which contains information about the file, but not the actual contents.
How do I get the actual text/html contents from the file?
I don't want to save it to my server, just pass on the content to my app and get rid of the file, so I don't want to use a module like formidable.
Can anyone help please?
Thank you!
The file is saved by default in a temporary folder (likely /tmp). You need to open the file, read its contents, and then delete it.
You'll want to use this API: http://nodejs.org/api/fs.html
And you could do this:
fs = require('fs');
fs.readFile(req.files.path, function (err, data) {
if (err) throw err;
// data will contain your file contents
console.log(data)
// delete file
fs.unlink(req.files.path, function (err) {
if (err) throw err;
console.log('successfully deleted ' + req.files.path);
});
});
Use multer https://github.com/expressjs/multer with the option inMemory: true.
As a crude example you'll want to do something like this.
app.post('test', function(req, res, next) {
var result = '';
multer({
inMemory: true,
onFileUploadData: function(file, data) {
result += data;
},
onFileUploadComplete: function(file) {
console.log(result); // This is what you want
}
})(req, res, next);
});
I'm working on creating a simple file uploader on a node server with expressjs as the middleware. So far, the server side looks like:
app.post('/upload', function(req, res) {
console.log(req.files);
//Handle the file
fs.readFile(req.files.imageUploader.path, function(err, data) {
var newPath = __dirname;
console.log(newPath);
console.log(data);
fs.writeFile(newPath, data, function(err) {
console.log(err);
res.send("AOK");
});
});
});
Now, the log statement for __dirname is my source directory, as expected (C:\Development\GitHub\ExpressFileUpload), however an error is happening on the upload:
{ [Error: EISDIR, open 'C:\Development\GitHub\ExpressFileUpload']
errno: 28,
code: 'EISDIR',
path: 'C:\\Development\\GitHub\\ExpressFileUpload' }
I've tried changing the newPath to be / and ./ but no change, different errors, but still errors. Is it something to do with the double \\ in the path in the error? Am I missing something simple here? Thanks for the help, let me know if more info is needed.
The __dirname global object is a directory, not a file. Therefore, you can't open it for writing, which is what fs.writeFile() attempts to do in your script, hence the reason you are getting a EISDIR. Assuming you want the file to be written with the same name it was uploaded with, you can do this:
var file = req.files.imageUploader;
fs.readFile(file.path, function(err, data) {
var path = __dirname + '/' + file.name;
fs.writeFile(path, data, function(err) {
});
});