skip to Main Content

my program is meant to load an image, resize it, save it, send it to FTP server and then delete resized image. Full code – HERE

The problem I am encountering is after pressing a finish button from the file named AddBreedBuilder.java: program sends resized file to server, freeze for ~1 sec, and it is trying to remove resized file (but it is not possible).

I tried to use (at the moment this part is deleted from java file, line 165): File fileToDelete = new File(imgPath);
boolean success = fileToDelete.delete();
but success is always false. Only way to delete this file is to not run sendToFTP().

From what I think, my program is using this file during file delete operation, so it cannot be deleted.

My question is: is it possible to delay file delete till program unfreeze?
Or maybe there is way to send resized file without saving it?

2

Answers


  1. From what I think, my program is using this file during file delete operation, so it cannot be deleted.

    That is correct.

    The reason is that your sendToFTP method opens the file that it is sending to the server, but it doesn’t (ever) close it. Since the file is still open, Windows won’t let the app delete it

    Solution: modify your sendToFTP method so that the FileInputStream is always closed.

    Login or Signup to reply.
  2. Beyond the questions you’ve asked, a few things are wrong with the code itself and it affects the answers to the questions. I’ll address these later. However, to directly address your questions first:

    1. Yes. You can do this by starting a new thread that handles the FTP transmission, since the transmission is initiated as the result of a GUI event, so that it doesn’t freeze your application. (The event dispatch thread that handles the GUI only starts the new thread without waiting for it to finish.) In sendToFTP(), do:

      public static void sendToFTP(String fileName, String name) {
          Thread sender = new Thread() {
              public void run() {
                  FTPClient client = new FTPClient();
                  try {
                      FileInputStream fis = new FileInputStream(new File(fileName));
      
                      client.connect("serwer1978625.home.pl");
                      client.login("[email protected]", MyBreed.getPassword());
      
                      client.changeWorkingDirectory("/breeds");
                      client.setFileType(FTP.BINARY_FILE_TYPE);
      
                      client.storeFile(name, fis);
                      // client.rename(fileName, name); // not necessary
                      client.logout();
                      // At this point you must close the FileInputStream, since that is what is using the file, as you noticed.
                      fis.close();
                      // TODO: your code to delete the file comes in here, if everything goes well
                      // Alternatively, you could do these in the finally block to run irrespective of how the above code executes
                  }
                  catch (IOException e) {
                      e.printStackTrace();
                  }
                  finally {
                      try {
                          client.disconnect();
                      }
                      catch (Exception e) {
                          e.printStackTrace();
                      }
                  }
              }
      
          };
               // the event dispatch thread only starts the sender thread and exits this function,
          // hence no freezing occurs
          sender.start();
      }
      

      Then in the calling function, buildAdd()

      // ...
      sendToFTP(imgPath, userBreedInfo[0] + ".jpg");
      // ...
      
    2. You can definitely send the file (more precisely, the file contents) without having to produce the file at all. You can instead supply the BufferedImage directly to the sendToFTP() method, and then transform that to the required InputStream for client.storeFile(). In this case you don’t even need to store the file at all in the first place if you don’t need it on the local machine.

      public static void sendToFTP(BufferedImage bimage, String name) {
            // ... some code
            // Here we need an input stream for storeFile(), so we get that from an output stream
            // produced in turn by the buffered image
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            ImageIO.write(bimage, "png", outStream);
            InputStream is = new ByteArrayInputStream(outStream.toByteArray());
            // ... some code
            client.storeFile(name, is);
            // ... rest of code
      }
      

    Then in the calling function, buildAdd()

        // ...
        sendToFTP(bimage, userBreedInfo[0] + ".jpg");
        // ...
    

    Notice the change in the signature of the second version of sendToFTP(). You could play with this idea in a different way, and rather replace the file writing call in buildAdd() with this InputStream, and then pass the stream to sendToFTP().

    Note
    You can use the try-with-resources idiom for ensuring the streams used above are automatically closed: see
    here for example.

    Other issues addressed:

    1. No need to rename the file after storing on the FTP endpoint: just
      use the final name the first time.
    2. Be sure to close the streams. That’s what caused the error you reported.
    3. In the better case, no need to create a file on the local system in the first place (i.e. within buildAdd()).
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search