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
  • 398,947
  • 96
  • 818
  • 769
CodeGuy
  • 28,427
  • 76
  • 200
  • 317
  • 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.

Farvardin
  • 5,336
  • 5
  • 33
  • 54
An̲̳̳drew
  • 13,375
  • 13
  • 47
  • 46
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,460
  • 11
  • 57
  • 87
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,853
  • 6
  • 84
  • 117
4

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
  • 135,866
  • 28
  • 264
  • 277
  • 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
  • 107,317
  • 23
  • 199
  • 210
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,520
  • 1
  • 26
  • 33
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
  • 73,284
  • 20
  • 146
  • 210