我想使用Apache公地网的FTP文件传输。

问题是文件被间歇地到达服务器损坏。通过“腐败”我的意思是winrar的告诉我一个zip文件具有“档案意外结束”。有时这些文件是完全空的。我注意到,这种情况多用于大型文件(100KB +),但确实发生了小文件太(20KB)。

我知道一个事实,即正在上载源zip文件是有效的,并且是唯一的243KB。

我没有得到任何错误/从代码中的异常。

下面是正在执行的代码:

    try
    {
        int CON_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(20); // fail if can't connect within 20 seconds
        int LIVE_TIMEOUT = (int) TimeUnit.MINUTES.toMillis(5); // allow up to 5 minutes for data transfers

        FTPClient client = new FTPClient();
        client.setConnectTimeout(CON_TIMEOUT);
        client.setDataTimeout(LIVE_TIMEOUT);
        client.connect(host);
        client.setSoTimeout(LIVE_TIMEOUT);
        client.login(user, pass);
        client.changeWorkingDirectory(dir);
        log("client ready");

        File file = new File(filePath);
        String name = new Date().getTime() + "-" + file.getName();

        InputStream fis = null;
        try
        {
            fis = new FileInputStream(file);
            if (!client.storeFile(name, fis))
                throw new RuntimeException("store failed");
            log("store " + name + " complete");
        }
        finally
        {
            IOUtils.closeQuietly(fis);
            try
            {
                client.logout();
                log("logout");
            }
            catch (Throwable e)
            {
                log("logout failed", e);
            }
            try
            {
                client.disconnect();
                log("disconnect");
            }
            catch (Throwable e)
            {
                log("disconnect failed", e);
            }
        }
    }
    catch (Throwable e)
    {
        log("transfer failed", e);
    }

和一些日志:

2010-08-10 21:32:38 client ready
2010-08-10 21:32:49 store 1281439958234-file.zip complete
2010-08-10 21:32:49 logout
2010-08-10 21:32:49 disconnect
2010-08-10 21:32:50 client ready
2010-08-10 21:33:00 store 1281439970968-file.zip complete
2010-08-10 21:33:00 logout
2010-08-10 21:33:00 disconnect
2010-08-10 21:33:02 client ready
2010-08-10 21:33:11 store 1281439982234-file.zip complete
2010-08-10 21:33:11 logout
2010-08-10 21:33:11 disconnect
2010-08-10 21:33:15 client ready
2010-08-10 21:33:25 store 1281439995890-file.zip complete
2010-08-10 21:33:26 logout
2010-08-10 21:33:26 disconnect
2010-08-10 21:33:27 client ready
2010-08-10 21:33:36 store 1281440007531-file.zip complete
2010-08-10 21:33:36 logout
2010-08-10 21:33:36 disconnect
2010-08-10 21:33:37 client ready
2010-08-10 21:33:48 store 1281440017843-file.zip complete
2010-08-10 21:33:48 logout
2010-08-10 21:33:48 disconnect
2010-08-10 21:33:49 client ready
2010-08-10 21:33:59 store 1281440029781-file.zip complete
2010-08-10 21:33:59 logout
2010-08-10 21:33:59 disconnect
2010-08-10 21:34:00 client ready
2010-08-10 21:34:09 store 1281440040812-file.zip complete
2010-08-10 21:34:09 logout
2010-08-10 21:34:09 disconnect
2010-08-10 21:34:10 client ready
2010-08-10 21:34:23 store 1281440050859-file.zip complete
2010-08-10 21:34:24 logout
2010-08-10 21:34:24 disconnect
2010-08-10 21:34:25 client ready
2010-08-10 21:34:35 store 1281440065421-file.zip complete
2010-08-10 21:34:35 logout
2010-08-10 21:34:35 disconnect

请注意,所有这些在15秒内被完整的,并且所有的服务器上生成的文件的已损坏。

我还测试不设置任何超时和问题仍然存在。

有帮助吗?

解决方案

共享FTP默认为ASCII文件类型。你想与像一个zip文件的二进制数据处理时,将其设置为二进制。

HTTP://commons.apache .ORG /净/ API /组织/阿帕奇/公地/净/ FTP / FTPClient.html

  

有FTPClient的默认设置是为它使用FTP.ASCII_FILE_TYPE,FTP.NON_PRINT_TEXT_FORMAT,FTP.STREAM_TRANSFER_MODE,和FTP.FILE_STRUCTURE。直接支持的唯一文件类型FTP.ASCII_FILE_TYPE和FTP.BINARY_FILE_TYPE。

您想要做setFileType(FTP.BINARY_FILE_TYPE)您发送文件之前。

其他提示

我有这个问题,尽管指定binary file type所以我写代码来验证通过散列MD5上传的文件:

public void upload(String sourceFilePath) throws Exception
{
    while (true)
    {
        // Upload
        File sourceFile = new File(sourceFilePath);
        String sourceFileHash = MD5Checksum.getMD5Checksum(sourceFilePath);
        String remoteFile = sourceFile.getName();

        try (InputStream inputStream = new FileInputStream(sourceFile))
        {
            boolean successful = ftpClient.storeFile(remoteFile, inputStream);

            if (!successful)
            {
                throw new IllegalStateException("Upload of " + sourceFilePath + " failed!");
            }
        }

        // Download
        File temporaryFile = File.createTempFile("prefix", "suffix");
        try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(temporaryFile)))
        {
            boolean successful = ftpClient.retrieveFile(remoteFile, outputStream);

            if (!successful)
            {
                throw new IllegalStateException("Download of " + sourceFilePath + " failed!");
            }
        }

        String downloadFileHash = MD5Checksum.getMD5Checksum(temporaryFile.getAbsolutePath());
        Files.delete(temporaryFile.toPath());

        // Make sure the file hashes match
        if (sourceFileHash.equals(downloadFileHash))
        {
            break;
        }
    }
}

MD5Checksum.java

import java.io.*;
import java.security.MessageDigest;

public class MD5Checksum
{
    private static byte[] createChecksum(String filename) throws Exception
    {
        try (InputStream fileInputStream = new FileInputStream(filename))
        {
            byte[] buffer = new byte[1024];
            MessageDigest complete = MessageDigest.getInstance("MD5");
            int numRead;

            do
            {
                numRead = fileInputStream.read(buffer);
                if (numRead > 0)
                {
                    complete.update(buffer, 0, numRead);
                }
            } while (numRead != -1);

            return complete.digest();
        }
    }

    public static String getMD5Checksum(String filename) throws Exception
    {
        byte[] checksum = createChecksum(filename);
        StringBuilder result = new StringBuilder();

        for (byte singleByte : checksum)
        {
            result.append(Integer.toString((singleByte & 0xff) + 0x100, 16).substring(1));
        }

        return result.toString();
    }
}

MD5码从采取此处

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top