I have created file storage system for my application. The problem I'm facing is that I'm unable to download the file from the server.
This is my code in the node js (express) controller
exports.downloadFiles = async (req, res, next) => {
const file = await File.findById(req.params.fileId);
return res.download(`uploads/${file.fileName}`, file.originalName);
}
I'm getting files correctly and on the frontend this is what I get.
But I should be prompted to save the file to my computer.
And here is my code that sends request to the backend
const requestData = { filePassword: password };
await axios.post(`${url-to-api}/file/${fileId}`, requestData);
I have tried looking into some answers (like this one), express documentation but can't find any solution.
Please note that these files are not in a static directory.
Please help me with this.
Related
I want to create file uploading web service with jwt Authentication such that peoples can upload there files to /upload route and I will use cloudinary service in my server to actually store them. User can also get their files using filename with /getfile route. Is there something else I should add in my project?
In order for the express server to be able to take a file as an input I would use the package Express file-upload in order to achieve this. The docs are super simple for this one.
Inside of your server.js file:
// setting temp files location
app.use(fileUpload({
useTempFiles : true,
tempFileDir : '/tmp/'
}));
upload route:
app.post('/upload', function(req, res) {
console.log(req.files.foo); // the uploaded file object
res.download('/report-12345.pdf')
});
This file obeject caqn then be used to save the file wherever you desire.
For sending the file back to the user Express also has a feature for this which is documented here
getfile route:
app.get('/getfile', function(req, res) {
// whatever file to be downloaded here
res.download('/report-12345.pdf')
});
Hope that's what you were asking for. Thanks!
I'm trying to allow a user to be able to download a zip folder from a server via an express JS api call. I've created my folder with: zip -r download.zip folder-to-zip and am struggling to get it to download.
It seems if I make a GET request to some endpoint, it only downloads it to the server rather than the browser, my endpoint is:
router.get('/download', (req, res) => {
res.download('download.zip')
})
I need to attach something to a button that'll download this zip folder.
I haven't tested this, I'll update my answer when I have.
But I think doing something like:
router.get('/download', (req, res) => {
res.setHeader('Content-type','application/zip');
res.sendFile(__dirname + '/download.zip');
})
This is usually how I download files via express.
I need to access FTP in another server (Ubuntu).
My Node.js API receive an image from user, and then needs to upload it to another server using FTP connection. However, if user folder doesn't exist, I need to create folder before sending the image.
How can i do this?
I'm using express-upload to get files:
const express = require('express');
const upload = require('express-fileupload');
const app = express();
app.use(upload());
app.use('/upload', async (req, res, next) => {
console.log(req.files.image);
})
You can use Basic FTP, an FTP client module, and use its ensureDir() method to implement the requirement "if user folder doesn't exists, I need to create folder before sending image".
According to its document:
...we make sure a remote path exists, creating all directories as necessary.
await client.ensureDir("my/remote/directory")
Then, you can send the image using its upload() method.
My Angular app sends a FormGroup to a Node.js server & then sends that form content via an Email.
At the moment, I can populate the email body like so:
<tr>
<th>Town</th><td>${content['formBody']['personalInfo']['town']}</td>
</tr>
and so on...
But, my form also has a File Upload control which I want to use to add file attachments to the email also.
Here is what I have at the moment:
<td>${content['formBody']['send']['fileUpload']}</td>
But instead of the actual selected file, "object Object" is appearing in the email body currently.
Is there a way I can attach the selected files to the email using the above approach, or is there a different way? Thanks a lot
What are you using in Node.js for getting the files?
A few months ago I needed to upload files and used Multer, a npm package for handling formdata files in node js. With it, you can use the files received on the backend and put it on the email.
In the frontend file
//Method to do the request
superagent
.post(/register")
.attach("avatar", uploadedImage)
uploadedImage has the image content that you get in the VueJS component
In the backend file
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
import fs from 'fs-extra'
router.post('/register', upload.single('avatar'), (req, res, next) => {
return fs.readFile(req.file.path)
.then(content => {
// The content of the file
})
}
For more information, here you have the answer Accessing data sent as FormData using Axios
Does it help?
I have a react frontend and a nodejs/express backend. The backend can serve files (downloads) via a protected route:
GET /api/file/:id
When the frontend wants to start a file download, it sends a request to this endpoint using this code (and the Authorization header is set with a valid token):
axios.get(`${apiURL}/file/${id}`)
.then(file => {
...
})
The backend responds with this code:
router.get('/file/:id', requireAuth, = (req, res, next) => {
...
res.set('Content-Type', 'application/pdf');
res.download(file.path, file.filename);
};);
This works fine: the download starts and the binary data is present in the file object of the .then() case of the axios call.
My question:
Instead of downloading the complete file I would like to pass the file to the browser BEFORE the file download starts, so that the browser handles the download like a usual browser-triggered-download, where the browser prompts wether it should download or display the file. How can this be done...?
The solution:
Thanks to #FakeRainBrigand tip I added token based authorization via request parameters to the route (using passport strategy):
const jwtOptions = {
jwtFromRequest: ExtractJwt.fromExtractors([
ExtractJwt.fromHeader('authorization'),
ExtractJwt.fromUrlQueryParameter('token'),
]),
secretOrKey: secretKey,
};
Now I can pass the download directly to the browser to handle it:
window.location.href = `${apiURL}/file/${_id}?token=${token}`;
The Authorization header is going to cause issues here. You should use cookies, at least for this feature. Otherwise, you'll have to include a token in the URL.
The two solutions are window.open in response to an event, or navigating to the url (e.g. location.href = '...').
At least in some browsers, they won't actually navigate when there's a file download, despite you changing the location.