How do I upload file to FTP server?

This example demonstrates how to upload file to FTP server.

package org.kodejava.commons.net;

import org.apache.commons.net.ftp.FTPClient;

import java.io.IOException;
import java.io.InputStream;

public class FTPUploadDemo {
    public static void main(String[] args) {
        FTPClient client = new FTPClient();
        String filename = "data.txt";

        // Read the file from the resources folder.
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        try (InputStream is = classLoader.getResourceAsStream(filename)) {
            client.connect("ftp.example.com");
            boolean login = client.login("demo", "password");
            if (login) {
                System.out.println("Login success...");

                // Store file to server
                client.storeFile(filename, is);
                client.logout();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Maven Dependencies

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.10.0</version>
</dependency>

Maven Central

Wayan

37 Comments

  1. Hi,

    I am trying to upload a file of 3MB to FTP server using that code, but when I run it, it uploads only 40KB of the file. What to do?

    Thanks,
    Eden

    Reply
    • Hi Eden,

      Did you get any error message when uploading the file? You can try to call the client.getReplyCode() and client.getReplyString() to see if any error occurred while uploading. Just print the reply code and reply string message using System.out.println() after the client.storeFile() line.

      Reply
  2. I am getting below exception can you pls help me. Thanks in advance

    java.net.ConnectException: Connection timed out: connect
        at java.net.TwoStacksPlainSocketImpl.socketConnect(Native Method)
        at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
        at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
        at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
        at java.net.PlainSocketImpl.connect(Unknown Source)
        at java.net.SocksSocketImpl.connect(Unknown Source)
        at java.net.Socket.connect(Unknown Source)
        at org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:762)
        at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:565)
        at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:557)
        at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:1795)
        at ftp.UploadFile.main(UploadFile.java:33)
    
    Reply
    • If you use another FTP client program to access the FTP server, can you connect to the FTP server? If you can connect, could it be an http proxy related issue?

      You could try use the FTPHTTPClient class instead of FTPClient. Using the FTPHTTPClient allows you to configure a proxy to connect to the FTP server. Do something like:

      FTPHTTPClient client = 
              new FTPHTTPClient("proxy.example.org", 8080, "username", "password");
      
      Reply
  3. org.apache.commons.net.ftp.FTPConnectionClosedException: FTP response 421 received.  Server closed connection.
        at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:360)
        at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:290)
        at org.apache.commons.net.ftp.FTP.sendCommand(FTP.java:474)
        at org.apache.commons.net.ftp.FTP.sendCommand(FTP.java:547)
        at org.apache.commons.net.ftp.FTP.user(FTP.java:693)
        at org.apache.commons.net.ftp.FTPClient.login(FTPClient.java:872)
        at javaapplication1.UploadFile.main(UploadFile.java:26)
    

    Can’t upload my file to my server, please help me Sir.

    Reply
    • Error 421 Service not available, closing control connection. Error 421 User limit reached Error 421 You are not authorized to make the connection Error 421 Max connections reached Error 421 Max connections exceeded.

      One of these errors could be related to your problem. Have you try to restart your FTP service and retry the process?

      Reply
  4. Hi – I will have to copy xml file from local machine to both Windows and Linux servers through soapui. Can you please let me know through sopaui? Is there any setting that we can enable to proceed with this?

    Reply
    • Hi Maciekk,

      The code snippet above read the file from resources directory. In a maven project this will be src/resources/data.txt. If you want to read the file from an absolute path you can modify the code to be like:

      var filename = "t:/kotlin/mk.txt";
      
      try (InputStream is = new FileInputStream(filename)) {
          ...
      }
      
      Reply
      • I’m just getting started with the Kotlin language. I can’t cope with converting your code to Kotlin. Can you help?

      • I was able to login but I cannot upload the file.

        val classLoader = Thread.currentThread().contextClassLoader
        try {
            val inputStream = FileInputStream(filename_sciezka)
            classLoader.getResourceAsStream(filename_sciezka).use { `is` ->
                client.connect("ftp.***.com.pl")
                val login: Boolean = client.login("*****", "****")
                if (login) {
                    println("Logowanie z sukcesem")
                }
            }
        }
        
  5. This is what the current code looks like.

    val classLoader = Thread.currentThread().contextClassLoader
    try {
        classLoader.getResourceAsStream(filename).use { `is` ->
        client.connect("ftp.test.com.pl")
        val login: Boolean = client.login("123", "password")
    } catch (e: Exception) {
    }
    
    Reply
  6. Hi Maciekk,

    Here is a simple version using Kotlin:

    import org.apache.commons.net.ftp.FTPClient
    import java.io.FileInputStream
    
    fun main() {
        val client = FTPClient()
        val filename = "F:/data.txt"
        FileInputStream(filename).use {
            client.connect("localhost")
            val login = client.login("demo", "password")
    
            if (login) {
                client.storeFile("abc.txt", it)
    
                client.logout()
                client.disconnect()
            }
        }
    }
    
    Reply
  7. Hi,

    I entered the code in Android Studio. I cannot import org.apache.commons.net.ftp.FTPClient. I see commons in red. Intellij IDEA has approx.

    Reply
    • Hi,

      Have you add the Apache Commons Net dependency in your module’s build.gradle file?

      dependencies {
          ...
          ...
          implementation 'commons-net:commons-net:3.8.0'
      }
      
      Reply
  8. Is it possible to write variables directly to a file on FTP? I would like to skip operations on the local device because it is too difficult for me now.

    Reply
    • Hi,

      By writing variables I assume that you want to upload some string values to the FTP server.

      If that’s correct, then you can convert the string into an InputStream and send it to the FTP server.

      String text = "Hello World!";
      InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
      
      Reply
  9. Yes, I write some string e.g. (sum1 = 1, sum2 = 2 …)
    Can you tell us how it will be written in Kotlin?
    One more request. what it will look like the other way (reading).

    Reply
    • Hi,

      You can do something like this in Kotlin.

      val text: String = "Hello World!"
      val inputStream : InputStream = ByteArrayInputStream(text.toByteArray(Charsets.UTF_8))
      

      or

      val text: String = "Hello World!"
      val inputStream = text.byteInputStream(Charsets.UTF_8)
      
      Reply
  10. Thank you.
    I have one more question. I am trying to save a file (not ftp) on an Android device :-). I found materials but all of them use “context”. Whatever I do, context lights up red.

    One code example I found on the web:

    val filename = "myfile"
    val fileContents = "Hello world!"
    context.openFileOutput (filename, Context.MODE_PRIVATE) .use {
        it.write (fileContents.toByteArray ())
    }
    
    Reply
  11. Uploading to ftp works, but when I put the code into android (HomeViewModel), the program cannot log into the ftp server. Please help. Coffee is on 🙂

    HomeViewModel
    Code:

    private fun zapis_string_ftp() {
        viewModelScope.launch(Dispatchers.IO) {
            val client = FTPClient()
            val text: String = "Hello World!"
            val inputStream = text.byteInputStream(Charsets.UTF_8)
    
            //val filename = "t:/kotlin/mk.txt"
            inputStream.use {
                client.connect("ftp.test.com.pl")
                val login = client.login("123456", "password")
    
                if (login) {
                    client.storeFile("abc.txt", it)
                    println("it = $it")
                   // println("Client = $client")
                    //println("Text = $text")
    
                    client.logout()
                    client.disconnect()
                    val a = Math.random()
                    val b = Math.random()
    
                    _viewState.value = viewState.value.copy(
                        result = a + b
                    )
                }
            }
        }
    }
    
    Reply
  12. Hi,

    I guess you get an error like android.os.NetworkOnMainThreadException in your application. This exception thrown because you cannot perform networking operation on the main thread. You can use the java.util.concurrent.ExecutorService to execute it in a different thread.

    You can do something like this:

    import java.util.concurrent.ExecutorService
    import java.util.concurrent.Executors
    
    class MainActivity : AppCompatActivity() {
        val executorService: ExecutorService = Executors.newFixedThreadPool(4)
    
        ...
        ...
    
        fun zapisStringFtp(view: View) {
            executorService.execute(Runnable {
                val client = FTPClient()
                val text: String = "Hello World! Hello World! Hello World!"
                val inputStream : InputStream = ByteArrayInputStream(text.toByteArray(Charsets.UTF_8))
                inputStream.use {
                    client.connect("192.168.0.103", 21)
                    val login = client.login("demo", "password")
                    client.enterLocalPassiveMode()
    
                    if (login) {
                        client.storeFile("abc.txt", it)
                    }
                    client.disconnect()
                    client.logout()
                }
            })
        }
    }
    

    And also add to AndroidManifest.xml

    <uses-permission android:name="android.permission.INTERNET" />
    
    Reply
  13. Works 🙂 but …
    the zapisStringFtp function is called each time Button is clicked. After the 4th click, the program (debug) throws an error: E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-4

    Reply
  14. E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-4
        Process: com.mmajka.composemvvmsample, PID: 5621
        java.lang.Error: org.apache.commons.net.ftp.FTPConnectionClosedException: FTP response 421 received.  Server closed connection.
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1173)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
            at java.lang.Thread.run(Thread.java:923)
         Caused by: org.apache.commons.net.ftp.FTPConnectionClosedException: FTP response 421 received.  Server closed connection.
    
    Reply
    • Hi,

      Good to know that it work!

      This error FTP response 421 received. Server closed connection. can be cause by the server connection limit. Because we create a new connection on every upload without closing the previous one.

      Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.