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

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.

Related

Is there a way to save a file to Heroku from a click via Puppeteer - NodeJs

I am using NodeJs & Puppeteer to access a web page and click a button which downloads a csv file. Locally this all works fine - I assign a path for the download and it saves it into the targeted folder. However, when running this deployed through Heroku, I can see that the Puppeteer script runs yet no file is downloaded. I assume this is an issue with saving files to Heroku. I realise Heroku uses ephemeral hard disks and I am fine with the csv file being deleted in a short period of time, I just need to read the data, handle it & then pass it to the frontend.
I have this bit of code which saves the csv file to my local folder destination.
const client = await page.target().createCDPSession();
await client.send('Page.setDownloadBehavior', {
behavior: 'allow',
downloadPath: downloadLocation, // Set download location
});
const csvButtonName = '.widget-actions-item';
await page.waitForSelector(csvButtonName);
await page.hover(csvButtonName);
await page.click(csvButtonName); //Downloads the csv file
I can my same directory structure on Heroku but cannot find the attempted csv download file.
Any help is appreciated.

puppeteer fileChooser: how to use URL instead of local file path?

I have the http link of a video file (cloud storage) and I want to select that file in filechooser.
I am using cloud hosting (glitch), so I don't want to store that file to local storage.
const [fileChooser] = await Promise.all([
page.waitForFileChooser(),
page.click('#select-files-button')
]);
await fileChooser.accept(["https://examle.mp4"]);
It only seems to accept a local file path, can anyone help me?
As you could have guessed, it obviously accepts only local files, you can download your desired file first (with request module or even http(s?) module), then pass it to puppeteer.

React_Display Image from server side into Client

I have a code that allows me to send files to server folder uploads using multer from react client side the process of sending data to server works perfectly and also getting back the file from server works perfectly.
The client side is running under 3000 and the server is running under 4000 .
the problem that I'm facing right now is displaying the file on the front part for ex an img
<img
src={`http:\\localhost:4000\\server\\${text}`}
className="messageText colorWhite"
alt="img"
/>
the image of the error is below
the text contains uploads/image1.jpg
when I inspect the content I found this
which mean that the image is well called from server side
Could it be possible to help me on this?
Best Regards,
The upload folder which contains the files is not being served up by the server at localhost:4000.
You must server the files in the uploads folder first. For eg in an express server you can access the files by specifying this route
app.get('/uploads/:filename', (req, res) => {
res.sendFile(req.params.filename, {root: path.join(__dirname, '/uploads')});
})
Now setting src=http://localhost:4000\uploads\img.png would get the image img.png stored in the uploads folder
As an alternative solution, you can server up the entire uploads folder by
app.use(express.static("uploads"));
Make sure you specify the full path in "uploads"

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.

file download from ftp server in nodejs

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

Resources