0

I am trying to upload a .zip File with my Java application to an FTP server using the Apache Commons Net FTPSClient.

<pre><code>import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.UUID;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPSClient;

public class FTPUploader {
    /**
     * Zips the source file first and then uploads it to the ftp server
     * @param source - The file to be uploaded
     * @param target - The file on the ftp server to upload to
     */
    public static void upload(String source, String target){
        BufferedInputStream stream = null;
        File zippedFile = new File("/temp/"+UUID.randomUUID()+".zip");
        File targetFile = new File(target);
        FTPSClient client = new FTPSClient();
        System.out.println("[FTPClient] Starting Upload of "+source+" to "+target);
        try {
            //Establish connection to FTP Server
            client.connect("localhost");
            client.login("user", "password"); //changed
            client.setFileType(FTP.BINARY_FILE_TYPE);
            client.enterLocalPassiveMode();
            client.execPBSZ(0);
            client.execPROT("P");
            //Get the original File
            File file = new File(source);
            //Zip the file before uploading
            if(file.isDirectory()){
                ZipUtil.zipDirectory(source, zippedFile.getPath());
            }
            else{
                ZipUtil.zipFile(source, zippedFile.getPath());
            }
            //Go to the directory on the ftp server
            String directoryPath = targetFile.getParentFile().getPath();
            //If it doesn't exist create it
            if(!client.changeWorkingDirectory(directoryPath)){
                client.makeDirectory(directoryPath);
                client.changeWorkingDirectory(directoryPath);
            }
            //Create an InputStream of the zipped file to be uploaded
            stream = new BufferedInputStream(new FileInputStream(zippedFile));
            //Store zipped file to server
            if(client.storeFile(targetFile.getName(), stream)){
                System.out.println("[FTPClient] Done!");
            }
            else{
                System.out.println("[FTPClient] Upload failed: "+client.getReplyString());
            }
            //Finish up
            client.logout();
        } catch (IOException e) {
            System.out.println("[FTPClient] Error! Last Reply: "+client.getReplyString());
            e.printStackTrace();
        } finally {
            try {
                if (stream != null) {
                    stream.close();
                }
                client.disconnect();
                zippedFile.delete();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

org.apache.commons.net.io.CopyStreamException: IOException caught while copying.
    at org.apache.commons.net.io.Util.copyStream(Util.java:136)
    at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:675)
    at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:639)
    at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:2030)
    ... 2 more
 Caused by: java.net.SocketException: Broken pipe (Write failed)
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
    at sun.security.ssl.OutputRecord.writeBuffer(OutputRecord.java:431)
    at sun.security.ssl.OutputRecord.write(OutputRecord.java:417)
    at sun.security.ssl.SSLSocketImpl.writeRecordInternal(SSLSocketImpl.java:886)
    at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:857)
    at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
    at java.io.BufferedOutputStream.write(BufferedOutputStream.java:126)
    at org.apache.commons.net.io.Util.copyStream(Util.java:124)
    ... 5 more</code></pre>

Things I checked:

  • Connection to FTP Server is working
  • Login is successful
  • Directory on FTP Server is created successfully
  • Empty .zip File with correct name is created on FTP Server
  • Permission on remote Directory is 755 (writing possible)
  • Both local and remote File Paths are correct and local file exists

Anyone know how to solve the error?

HeaX
  • 11
  • 1
  • 5
  • Please show your code. If it is *very* lengthy, you might upload it to something like pastebin. – Binarus Aug 07 '18 at 16:31
  • I've added the code, I hope it provides you with the relevant information. – HeaX Aug 07 '18 at 17:07
  • Do you get the problem with any file or just zip files? FTPS only? Or even with plain FTP? Post shortest possible code that still reproduces the problem (no zipping, no changing/creating of directories, unless really needed to reproduce the problem) – Martin Prikryl Aug 07 '18 at 19:23
  • What file type would you suggest? I cannot connect to the server using plain FTP as it responds with 550 SSL/TLS required on control channel (or data channel, for that matter) Since the remote file is created but empty I think removing the directory or zipping stuff won't change anything, so I might as well just remove it from the code. – HeaX Aug 07 '18 at 19:45
  • Just try plain .txt file. Or some image format. – Martin Prikryl Aug 08 '18 at 05:43

1 Answers1

1

The problem was caused by the FTP Server. It had a setting that forces FTP clients to reuse their SSL session from the control channel on the data channel, which the apache commons FTP client apparently does not do. Disabling the requirement on the server using 'TLSOptions NoSessionReuseRequired' solved the issue.

It is worth noting though that the requirement seems to have a security background as the data channel may be hijacked when it does not need to use the same SSL session. See this answer: https://stackoverflow.com/a/32404418/10173457

HeaX
  • 11
  • 1
  • 5