Reputation: 353
How do you retrieve a file if your node express web service is on a linux server (ubuntu) and you need to download files from a windows server?
2 Valid Options:
Windows Servers do not support SFTP/SSH. There are some ways to do this (with https://winscp.net/eng/docs/guide_windows_openssh_server and https://www.npmjs.com/package/ssh2) but this requires our server administrator to install on windows and it isn't fully supported by Microsoft.
You could use FTP/FTPS. There's this package: https://github.com/Atinux/node-ftps I just wasn't able to get this to work but it should be a viable option.
How can you do this from the operating system directly instead of relying on third-party node packages?
Upvotes: 1
Views: 1206
Reputation: 353
You can use smbget (linux utility included with https://linux.die.net/man/1/smbget ) and then just use node child_process spawn to call the function.
Just replace [workgroup], [username], [password], [serveraddress], and [path] with your own information here.
function getFile(file) {
return new Promise(function(resolve, reject) {
var tempFilePath = `/tmp/${file}`; // the linux machine
var remoteFile = require('child_process').spawn('smbget', ['--outputfile', tempFilePath, '--workgroup=[workgroup]', '-u', '[username]', '-p', '[password]', `smb://[serveraddress]/c$/[path]/[path]/${file}`]);
remoteFile.stdout.on('data', function(chunk) {
// //handle chunk of data
});
remoteFile.on('exit', function() {
//file loaded completely, continue doing stuff
// TODO: make sure the file exists on local drive before resolving.. an error should be returned if the file does not exist on WINDOWS machine
resolve(tempFilePath);
});
remoteFile.on('error', function(err) {
reject(err);
})
})
}
The code snippet above returns a promise. So in node you could send the response to a route like this:
var express = require('express'),
router = express.Router(),
retrieveFile = require('../[filename-where-above-function-is]');
router.route('/download/:file').get(function(req, res) {
retrieveFile.getFile(req.params.file).then(
file => {
res.status(200);
res.download(file, function(err) {
if (err) {
// handle error, but keep in mind the response may be partially sent
// so check res.headersSent
} else {
// remove the temp file from this server
fs.unlinkSync(file); // this delete the file!
}
});
})
.catch(err => {
console.log(err);
res.status(500).json(err);
})
}
The response will be the actual binary for the file to download. Since this file was retrieved from a remote server, we also need to make sure we delete the local file using fs.unlinkSync().
Use res.download to send the proper headers with the response so that most modern web browsers will know to prompt the user to download the file.
Upvotes: 3