27

I'm trying to do a VERY simple file upload. I want a Java FTPClient that can upload any file I tell it to. But the pdf always gets all messed up and my pdf editor (Adobe) won't open it, saying there is an I/O error.

I'm using the following class:

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

    FTPClient client = new FTPClient();
    FileInputStream fis = null;

    try {
        client.connect("mydomain.com");
        client.login("user", "password");

        String filename = "myPDF.pdf";
        fis = new FileInputStream(filename);

        client.storeFile("temp.pdf", fis);
        fis.close();
        client.logout();
    } catch (IOException e) {
        e.printStackTrace();
    }

Why doesn't this work, and how do I fix it?

skaffman
  • 390,936
  • 96
  • 800
  • 764
CodeGuy
  • 27,591
  • 71
  • 194
  • 314
  • Did you try the answers in your question from half an hour ago? http://stackoverflow.com/questions/5925438/url-connection-ftp-in-java-simple-question – Aleadam May 08 '11 at 04:47
  • yup, I'm using an FTPClient now. The question is completely different. – CodeGuy May 08 '11 at 04:51

8 Answers8

32

It doesn't work because the default transfer mode for FTPClient is FTP.ASCII_FILE_TYPE. You just need to update the configuration to transfer in binary mode.

Taher Khorshidi
  • 5,168
  • 5
  • 31
  • 53
An̲̳̳drew
  • 12,585
  • 12
  • 46
  • 45
24

Add this to your file

ftp.setFileType(FTP.BINARY_FILE_TYPE, FTP.BINARY_FILE_TYPE);
ftp.setFileTransferMode(FTP.BINARY_FILE_TYPE);

I had the same problem with xlsx files and this was a good solution.

shanethehat
  • 15,360
  • 11
  • 55
  • 85
Stevan Buzejic
  • 273
  • 2
  • 2
  • 6
    I don't think you want to call setFileTransferMode like that -- according to the JavaDoc it's meant to take only the FTP.*_TRANSFER_MODE constants. – Peter Becker Mar 04 '13 at 03:23
  • 2
    -1, this answer is wrong and result in wasting my time. Only ftp.setFileType(FTP.BINARY_FILE_TYPE); is required, il you put the 2nd param ftp.setFileType(FTP.BINARY_FILE_TYPE, FTP.BINARY_FILE_TYPE) the file il corrupted ( with pdf and xls ) – amdev Jun 13 '16 at 11:45
  • Has something changed at FTPClient? Because for me it is FTPClient.BINARY_FILE_TYPE. – sigi Oct 15 '17 at 13:18
10

It's often forgotten that FTP has two modes of operation - one for text files and the other for binary (image) files. In the good old days, connecting from a command line ftp client, we'd carefully remember to set the transfer mode before requesting a file - or we'd run into exactly the sort of problem you seem to be having. Today a lot of situations seem to default to binary, but not apparently yours.

You probably need to tell your ftp implementation to transfer in binary/image mode.

Chris Stratton
  • 39,254
  • 6
  • 81
  • 117
3

Try to use BufferedInputStream, this is a (working) code sample:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
res = client.storeFile("File Name", bis);
bis.close();
client.logout();
MByD
  • 133,244
  • 25
  • 260
  • 270
  • Two short questions - have you tried to open the file on the client machine? have you tried sending a different file? – MByD May 08 '11 at 04:44
  • yes, other files are fine. and what do you mean open it on the client machine? basically, after I upload it, I download it to my local machine. it's an ftp on a website I own. – CodeGuy May 08 '11 at 04:47
  • did you have any success opening the file before uploading it? maybe you have a problem in the download mechanism? --I'm not sure about those, just trying to help :S – MByD May 08 '11 at 04:51
  • 1
    yeah. the original file is just fine. ugh I'm not sure why it doesn't work. It works fine for other files I've tried like txt files. something special about pdfs. – CodeGuy May 08 '11 at 04:53
2

From documentation

This method does NOT close the given InputStream.

So close the FileInputStream before calling logout()

Bala R
  • 104,615
  • 23
  • 192
  • 207
1

Try this.

objFtpClient.setFileType(FTP.BINARY_FILE_TYPE);

objFtpClient.setFileTransferMode(FTP.BINARY_FILE_TYPE);

objFtpClient.enterLocalPassiveMode();
JK Patel
  • 31
  • 4
1

For Me only ftp.setFileType(FTP.BINARY_FILE_TYPE, FTP.BINARY_FILE_TYPE) worked, while when I was using ftp.setFileTransferMode(FTP.BINARY_FILE_TYPE) File was getting corrupt.

Swarit Agarwal
  • 2,276
  • 22
  • 31
0

This looks like a bug in the Commons NET library, which affected version 3.0. Try a newer version (3.0.1), which fixed the bug.

Paŭlo Ebermann
  • 71,139
  • 18
  • 140
  • 206