2

I have a grails app which should upload a bunch of images to a server via FTP. To do that I`m using commons-net. What is weird is, that if I create a new connection for each file it works normal, but if I have connected once and then start sending the files, the files got corrupted! bellow is my code, which works but I dont want to create a new connection for each file:

    filesList.each{ f->

        String ftpUser = ConfigurationHolder.config.ftp.user
        String ftpPassword = ConfigurationHolder.config.ftp.password
        String ftpHost = ConfigurationHolder.config.ftp.host

        log.debug "ftp> ${ftpUser}@${ftpHost}"

        JakartaFtpWrapper ftp = new JakartaFtpWrapper();
        ftp.connectAndLogin(ftpHost, ftpUser, ftpPassword)
        ftp.setDataTimeout(1000*60*60*5)
        log.debug "Welcome message[${ftp.getReplyString()}]"
        log.debug "Current Directory[${ftp.printWorkingDirectory()}]";

        log.debug "remote dir[${remoteDir}]"
        ftp.makeDirectory(remoteDir)
        ftp.cwd(remoteDir)


        log.debug "uploading file path[${f}]..."
        ftp.binary()
        ftp.enterLocalPassiveMode()


        def input  = new FileInputStream(f.getAbsolutePath());
        OutputStream output = ftp.storeFileStream(f.getName())

        Util.copyStream(input, output);

        output.flush()
        input.close();
        output.close();

        ftp.logout();
        ftp.disconnect();
    }

If I remove the connect from the each, the images got corrupted! am I doing something wrong here?

EDIT**: This one DOES NOT work:

    String ftpUser = ConfigurationHolder.config.malibu.ftp.user
    String ftpPassword = ConfigurationHolder.config.malibu.ftp.password
    String ftpHost = ConfigurationHolder.config.malibu.ftp.host

    log.debug "ftp> ${ftpUser}@${ftpHost}"

    JakartaFtpWrapper ftp = new JakartaFtpWrapper();
    ftp.connectAndLogin(ftpHost, ftpUser, ftpPassword)
    ftp.setDataTimeout(1000*60*60*5)
    log.debug "Welcome message[${ftp.getReplyString()}]"
    log.debug "Current Directory[${ftp.printWorkingDirectory()}]";

    log.debug "remote dir[${remoteDir}]"
    ftp.makeDirectory(remoteDir)
    ftp.cwd(remoteDir)

    filesList.each{ f->
        log.debug "uploading file path[${f}]..."
        ftp.binary()
        ftp.enterLocalPassiveMode()

        def input  = new FileInputStream(f.getAbsolutePath());
        OutputStream output = ftp.storeFileStream(f.getName())

        Util.copyStream(input, output);

        output.flush()
        input.close();
        output.close();
    }

    ftp.logout();
    ftp.disconnect();

EDIT :

link for JakartaFtpWrapper : http://www.nsftools.com/tips/JakartaFtpWrapper.java

EDIT 2 :

I`ve already tried adding the ftp.binary() inside, the loop, or outsite. both doesnt work.

One interesting think about it, is, that always the LAST photo got right in the ftp server, it seems that the first ones are more corrupted then the last ones as well!

skaffman
  • 398,947
  • 96
  • 818
  • 769
Arthur Neves
  • 11,840
  • 8
  • 60
  • 73
  • 1
    could you post the code that _doesn't_ work? – Mat Jun 14 '11 at 21:17
  • Can you also post a link to the doc or source for JakartaFtpWrapper? – Freiheit Jun 15 '11 at 15:58
  • Ok thats a subclass of FTPCLient from apache commons, http://commons.apache.org/net/apidocs/index.html . Try searching for a similar problem with FTPClient and see if that helps. – Freiheit Jun 15 '11 at 19:17
  • I did already! i spend about 1 day trying to figure that on the net.. and nothing! – Arthur Neves Jun 15 '11 at 19:52
  • Do the calls to ftp.binary() and ftp.enterLocalPassiveMode() need to be in the loop? – Freiheit Jun 15 '11 at 20:05
  • I dont know. but Actually I have tried inside the loop as well as outside. and none worked! – Arthur Neves Jun 15 '11 at 21:53
  • 1
    One last option, get a good FTP client either commandline or FileZilla where you can get it to log what modes and settings it is using. Replicate this process in that client and see what FTP commands/settings it is using to send files. – Freiheit Jun 16 '11 at 13:46
  • funny! , we had the same thoughts, because i have already done that too! i got FileZilla and just copy the same code! and no success either! =*( – Arthur Neves Jun 16 '11 at 14:23

3 Answers3

5

Try setting the option in JakartaFtpWrapper to transfer in binary mode instead of ascii.

From related question: Java upload jpg using JakartaFtpWrapper - makes the file unreadable

Community
  • 1
  • 1
Freiheit
  • 8,408
  • 6
  • 59
  • 101
  • 1
    but I`ve already set to binary: ftp.binary() – Arthur Neves Jun 14 '11 at 23:14
  • Bugger, I missed that. If you open the file in a text editor and compare it to the original is anything different? If its large just use head or tail and compare a few lines. – Freiheit Jun 15 '11 at 02:26
  • Yeah. .they are different even if I open as image! we can see the bottom of the image gray! and what`s weird also is that the LAST image that a send it`s sending ok! but the other ones are crappy! – Arthur Neves Jun 15 '11 at 14:13
  • Could Util.copyStream be corrupting it? Can you change output to point to a local file then check that? – Freiheit Jun 15 '11 at 14:48
  • 1
    good one! but I`ve already tried to not use 'Util.copyStream' before, I was using normal byte transfer, but same problem! – Arthur Neves Jun 15 '11 at 15:36
1

I have two possible suggestions.

First you could try calling ftp.completePendingCommand() after you copy each stream just to see if it finishes before it tries the next transfer. (This is probably the more likely of my suggestions to actually help)

The other thing I was thinking is to remove the output.flush() command as usually this is called in output.close() though honestly if this turns out to be the case, I'll be very surprised.

Hope this helps!

Shaded
  • 17,276
  • 8
  • 37
  • 62
0

This is what I do, and it works for me:

OutputStream output;

output = new FileOutputStream(localDirectory);

//get the file from the remote system
ftp.setFileType(FTP.BINARY_FILE_TYPE);
ftp.setFileTransferMode(FTP.BINARY_FILE_TYPE);
ftp.retrieveFile(file.getName(), output);

//close output stream
output.flush();
output.close();

The key thing is to set the FileType with a correct type, maybe it could be FTP.BINARY_FILE_TYPE or FTP.IMAGE_FILE_TYPE

Jesse
  • 8,605
  • 7
  • 47
  • 57