commons-net ftp is uploading corrupted files

混江龙づ霸主 提交于 2019-12-03 14:16:54

Commons FTP defaults to ascii file types. You want to set it to Binary when dealing with binary data like a zip file.

From http://commons.apache.org/net/api/org/apache/commons/net/ftp/FTPClient.html

The default settings for FTPClient are for it to use FTP.ASCII_FILE_TYPE , FTP.NON_PRINT_TEXT_FORMAT , FTP.STREAM_TRANSFER_MODE , and FTP.FILE_STRUCTURE . The only file types directly supported are FTP.ASCII_FILE_TYPE and FTP.BINARY_FILE_TYPE .

you want to do setFileType(FTP.BINARY_FILE_TYPE) before you send the file.

I had this problem despite specifying binary file type so I wrote code to validate the uploaded file via MD5 hashing:

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();
    }
}

The MD5 code is taken from here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!