file download from ftp server in nodejs - node.js

I have web application where on button click invoking REST API which fetch list of files available in ftp server and displayed in div with hyperlink on file name as below.
for this I am using jsftp module.
ftp.ls(".", function(err, res) {
res.forEach(function(file) {
console.log(file.name);
//logic to display in div
});
});
I have another REST API for download file from FTP server which invoked on file name click present in div but it is downloaded in local directory where web application deploy and not in users system with below code, but I want when user click on file name that file should download in users system or computer. How I can achieve this.
ftp.get('remote/file.txt', 'local/file.txt', function(hadErr) {
if (hadErr)
console.error('There was an error retrieving the file.');
else
console.log('File copied successfully!');
});

Now that the file is on your machine you will want to actually server the file to the client when they click on the link. Using res.write something like: res.write(file, 'binary');
Here are some concepts that you'll find useful: Node.js send file to client

Related

Send file from Node using Express within a POST route

I need to send the client (browser) a file after the client invokes a POST endpoint within my API. I tried using res.download(filename) but while there's no error, it doesn't do anything, e.g., pop up a download dialog, open in default viewer, etc.
function onArchiveCompleted (res, zip) {
const archive = `${uuidv4()}.zip``zip.writeZip(archive)
res.download(archive)
}
The "res.download()" returns 200 but no file dialog is ever presented on the client. However, if you look in the Network panel (browser developer tools) you can see that the file contents were returned.
What am I doing wrong?
TIA

Generate .ics url like Basecamp in Nodejs

I am working on nodeJs(backend) and (Angular)
I want to generate a .ics file URL for google calendar and for Apple and Microsoft as a downloadable file.
I know there is a node module ics and I am using that, but that only creates a .ics file I want this to be unique for each user and also want this to delete automatically.
Also, it should automatically sync with the events added.
any suggestion for this?
I have been unable to find a way that would continually update someone's schedule since this would require continuous access to someone's calendar. While building a scheduling site I got around your storage and unique file problem by using a brute force solution.
First, as a client access the download endpoint an unique ics file is generated and stored as schedule_date_client-name.ics. This unique file is then sent to the user using res.download and promptly deleted using fs.unlink(path_to_file).
Here is an example of this in action :
try {
res.download(path, function(error){
if (error) {
console.log("Error : ", error)
}
fs.unlink(path, (error) => {
// log any error
if (error) {
console.log(error);
}
})
});
} catch (e) {
next(e);
}
The best way I found around this is to generate the .ics file as the user accesses a /download url endpoint. Send the file in a downloadable format using res.download in your controller file. Here is more information on the packages I used for this solution :
Node .ics : https://www.npmjs.com/package/ical-generator
Node file : https://nodejs.dev/learn/the-nodejs-fs-module
Require the modules :
const ical = require('ical-generator');
const fs = require("fs");

On trying to download file from Node JS, In browser getting error as: Failed network error

I am trying to download a file located in my storage in box.com.
When user made a api request with specific id then i am getting file url related to that id from box.com and in node js again making another api call to get the file chunks and returning it to the client.
Process is:
User make an api call as: /api?id=123 to node js
In node js, I am getting file url related to id 124.
Obtained file url is: https://box.com/xyz_123
Using this file url, I am making again an api call to the box server and getting file as chunk by chunk and returning it to client.
When the file is about to finish in 5 seconds, then in browser it is showing error as: Failed network error.
Here is the way i am calling the box url to get file streams and returning to client side chunk by chunk.
const creq = https.request(boxurl, (cres) => {
cres.setEncoding('utf8');
res.writeHead(cres.statusCode,
{
'Content-Length': cres.headers['content-length'],
'Content-Type': 'application/octet-stream',
'Content-Disposition' : cres.headers['content-disposition']
}
);
// wait for data
cres.on('data', function(chunk){
res.write(chunk);
});
cres.on('close', function(){
// closed, let's end client request as well
return res.end('Success');
});
cres.on('end', function(){
// finished, let's finish client request as well
return res.end('Success');
});
}).on('error', function(e) {
// we got an error, return 500 error to client and log error
return res.end(e.message);
});
creq.end();
File download mechanism working very well in my system.
When i deployed code to remote server and checking, then only this error is appearing.
Can any one please help me on this. How to solve this.
Thanks in advance.
To make use of the Box Node SDK you have to create a Box app in the Box Developer Console. Then you need to configure and authorise that app. An example can be found here
You can now write your node app that uses the Box SDK to talk to your Box app / account. An example of how to connect it up can be found here.
The code to download a file from Box can be found from Box's SDK documentation here. But before you can download a file you will need to discover its File Id by using other SDK methods such as getting a folder's items or search for content.
The folder id of your root folder in Box is always 0 which is a good place to start when searching for various file or folder id numbers.

Express - res.download not working correctly

So I'm attempting to download a file in the server which I get and place in my current directory and when I try to send it back to the user using res.download(file) it seems to send it as plain text instead of sending an attachment to download. I'm currently trying to send a .doc file.
http://expressjs.com/en/api.html#res.download
I have tried to set the headers res.setHeaders('Content-Disposition', 'attachment') but that doesn't seem to work either.
variable file currently has the path to the file exactly.
var file = path.join(__dirname, result)
res.download(file, result, function(err){
if(err){
console.log("err", err)
}
})

Node/Express: File not downloading using fs.pipe()

I'm having an issue downloading files to my local machine using fs.pipe() in my Node.js/Express cloud foundry application.
Basically, a POST request is sent to my server side code containing the file name my user wants to download. I access the file using the GET command from the npm module ssh2-sftp-client. Finally, this file gets saved to the users local downloads folder using the npm module downloads-folder to identify this location. The code looks like this:
app.post('/download-file', function(req, res) {
// Declare the files remote and local path as a variable.
const remoteFilename = 'invoice/csv/' + req.body.file;
const localFilename = downloadsFolder() + '/' + req.body.file;
// Use the SFTP GET command to get the file passing its remote path variable.
sftp.get(remoteFilename).then((stream) => {
// Download the file to the users machine.
stream.pipe(fs.createWriteStream(localFilename));
// Redirect user.
res.redirect('/invoice')
});
})
This works perfectly when running locally and the file gets downloaded with no issues. As this screenshot shows, the output for the destination file path is this:
However, when I push this to our cloud foundry provider using cf push, the application still works fine but when I want to download the file it fails. I get no errors when error catching, the only thing thats changed is that the output for the destination file path has changed to:
I have no idea why this is, this code works fine in Chrome, Safari when running locally but when hosted doesn't do anything. Can anyone explain what's going wrong here?
Many thanks,
G
// Download the file to the users machine.
It doesn't do that, though: it downloads the file to the machine on which the server code is running. That's why it seems to work when you run the server on localhost, because the server machine and the user machine are the same.
Offering the file as a download involves streaming the file through the response object, making sure that you set the correct header. Something like this:
sftp.get(remoteFilename).then((stream) => {
res.set('content-disposition', `attachment; filename="${ req.body.file }"`);
stream.pipe(res);
});
When offering a file as "attachment", it typically opens the download window of the browser and the browser stays on the same page. You can't both stream and perform a redirect, but because the browser doesn't change the URL, that should be okay.
Also, you have no control over where the user will download the file to. It may be the downloads folder, but they are free to chose another folder.

Resources