Java FTPClient如何绕过org.apache.commons.net.io.CopyStreamException:复制时捕获IOException

Java FTPClient如何绕过org.apache.commons.net.io.CopyStreamException:复制时捕获IOException,java,apache,file,ftp,copy,Java,Apache,File,Ftp,Copy,我正在尝试使用ApacheCommonsNetFTPSClient将带有Java应用程序的.zip文件上载到FTP服务器 <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

我正在尝试使用ApacheCommonsNetFTPSClient将带有Java应用程序的.zip文件上载到FTP服务器

<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>
我检查过的东西:

  • 与FTP服务器的连接正在工作
  • 登录成功
  • FTP服务器上的目录已成功创建
  • 在FTP服务器上创建了具有正确名称的空.zip文件
  • 远程目录的权限为755(可以写入)
  • 本地和远程文件路径都正确,并且本地文件存在

有人知道如何解决这个错误吗?

这个问题是由FTP服务器引起的。它有一个强制FTP客户端从数据通道上的控制通道重用SSL会话的设置,而apache commons FTP客户端显然没有这样做。使用“TLSOptions NoSessionReuseRequired”禁用服务器上的需求解决了问题


值得注意的是,该要求似乎具有安全背景,因为数据通道在不需要使用相同的SSL会话时可能被劫持。请查看以下答案:

请显示您的代码。如果它很长,你可以上传到pastebin之类的东西上。我已经添加了代码,我希望它能为你提供相关信息。你有没有发现任何文件或zip文件的问题?仅限FTPS?或者甚至使用普通FTP?发布仍然重现问题的尽可能短的代码(没有压缩,没有更改/创建目录,除非真的需要重现问题)您建议使用什么文件类型?我无法使用普通FTP连接到服务器,因为它在控制通道(或数据通道)上响应需要550 SSL/TLS,因为远程文件已创建但为空。我认为删除目录或压缩内容不会改变任何内容,所以我不妨将其从代码中删除。请尝试使用plain.txt文件。或者一些图像格式。