0

I want to download file using absolute FTP URL, like ftp://host:port/dir/file.extension

I've tried node-libcurl, wget, wget-improved, request. All failed saying that the protocol must be either HTTP or HTTPS.

There are FTP clients available for Node (available on npmjs). But, as per their documentation, they require creating a connection to FTP Server, change directory and then download it.

Is there any simple solution?

Himanshu Shekhar
  • 318
  • 9
  • 15

3 Answers3

3

I will outline a simple approach here (and no complete solution with code!). FTP is based upon TCP with a simple human readable protocol. In order to fetch a file from an FTP server you need to do the following:

  1. Create a TCP socket using net.Socket
  2. Use socket.connect to connect to your FTP server on port 21
  3. Communicate with the server using socket.write to send data and socket.on('data') to read data

An example of FTPs protocol for a simple file retrieval is provided in this blog post and can be summarized as follows:

  1. Connect to server using net.Socket.connect
  2. Set user with USER command
  3. Authenticate with PASS
  4. Go to desired directory using CWD
  5. Change to passive mode using PASV
  6. Read server reply to find out IP and port to connect to in order to fetch the file
  7. Open another socket on IP and port of previous step
  8. VoilĂ !
Yan Foto
  • 10,850
  • 6
  • 57
  • 88
3

Anyone wanting to have simple single line solution that in addition to FTP would also work with FTPS and SFTP, you can try ftp-any-get

import { getFile } from "@tpisto/ftp-any-get"

async function main() {
  // Fetch from FTP server
  let ftpFile = await getFile("ftp://demo:password@my-ftp-server.net/my-file.txt");

  // Fetch from FTP server using TLS
  let ftpsFile = await getFile("ftps://demo:password@my-ftp-server.net/my-file.txt");

  // Fetch file using SFTP. SFTP runs over the SSH protocol.
  let sftpFile = await getFile("sftp://demo:password@my-ftp-server.net/my-file.txt");
}
main();
tpisto
  • 31
  • 2
1

You can use , I don't know exactly how you did it, but here is some working code.

var Curl = require( 'node-libcurl' ).Curl,
    Easy = require( 'node-libcurl' ).Easy,
    path = require( 'path' ),
    fs   = require( 'fs' );

var handle = new Easy(),
    url    = 'ftp://speedtest.tele2.net/1MB.zip',
    // Download file to the path given as first argument
    //  or to a file named 1MB.zip on current dir
    fileOutPath = process.argv[2] || path.join( process.cwd(), '1MB.zip' ),
    fileOut     = fs.openSync( fileOutPath, 'w+' );

handle.setOpt( Curl.option.URL, url );

handle.setOpt( Curl.option.WRITEFUNCTION, function( buff, nmemb, size ) {

    var written = 0;

    if ( fileOut ) {

        written = fs.writeSync( fileOut, buff, 0, nmemb * size );

    }

    return written;
});

handle.perform();
fs.closeSync( fileOut );

The repository currently has one example showing how to download a file using wildcard matching, I just changed the URL to point directly at the file, and removed the WILDCARDMATCH and CHUNK_*_FUNCTION options.

suther
  • 12,600
  • 4
  • 62
  • 99
jonathancardoso
  • 11,737
  • 7
  • 53
  • 72