【问题标题】:Deleting file during FTP/Database connection failed在 FTP/数据库连接期间删除文件失败
【发布时间】:2019-08-15 12:28:50
【问题描述】:

我的程序是用来加载图像、调整大小、保存、发送到 FTP 服务器然后删除调整大小的图像。完整代码-HERE

我遇到的问题是从名为 AddBreedBuilder.java 的文件中按下 finish 按钮后:程序将调整大小的文件发送到服务器,冻结约 1 秒,然后它正在尝试删除调整大小的文件(但这是不可能的)。

我尝试使用(目前这部分已从 java 文件中删除,行 165):File fileToDelete = new File(imgPath); boolean success = fileToDelete.delete(); 但success 始终为false。删除此文件的唯一方法是不运行sendToFTP()。

从我的想法来看,我的程序在文件删除操作期间正在使用这个文件,所以它不能被删除。

我的问题是:是否可以延迟文件删除直到程序解冻? 或者也许有办法发送调整大小的文件而不保存它?

【问题讨论】:

    标签: java apache ftp delete-file


    【解决方案1】:

    除了您提出的问题之外,代码本身还有一些问题,它会影响问题的答案。我稍后会解决这些问题。但是,首先要直接解决您的问题:

    1. 是的。您可以通过启动一个处理 FTP 传输的新线程来执行此操作,因为传输是作为 GUI 事件的结果启动的,因此它不会冻结您的应用程序。 (处理 GUI 的事件调度线程只启动新线程而不等待它完成。)在sendToFTP() 中,执行:

      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("nissmel@chooseyourpuppy.pl", 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();
      }
      

      然后在调用函数中,buildAdd()

      // ...
      sendToFTP(imgPath, userBreedInfo[0] + ".jpg");
      // ...
      
    2. 您完全可以发送文件(更准确地说是文件内容),而根本无需生成文件。您可以改为将BufferedImage 直接提供给sendToFTP() 方法,然后将其转换为client.storeFile() 所需的InputStream。在这种情况下,如果您不需要在本地计算机上存储该文件,您甚至根本不需要存储该文件。

      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
      }
      

    然后在调用函数中,buildAdd()

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

    注意sendToFTP()第二版的签名变化。你可以用不同的方式来玩这个想法,而是用这个InputStream替换buildAdd()中的文件写入调用,然后将流传递给sendToFTP()。

    注意 您可以使用 try-with-resources 习惯用法来确保自动关闭上面使用的流:请参阅 以here 为例。

    解决的其他问题:

    1. 存储到 FTP 端点后无需重命名文件:只需 第一次使用最终名称。
    2. 确保关闭流。这就是导致您报告的错误的原因。
    3. 在更好的情况下,首先不需要在本地系统上创建文件(即在buildAdd() 内)。

    【讨论】:

    • name 变量不应在定义为 Thread 实例化器主体的新 lambda 范围内更改。所以创建另一个局部变量,可能是String outFileName = name + ".jpg"。然后改用client.storeFile(outFileName, fis)。更好的是,将您想要的确切名称传递给sendToFTP()(包括.jpg 扩展名,因此您只需在client.storeFile(name, fis) 中完全按原样使用name
    • 我已经编辑了答案以反映后一种方法。
    【解决方案2】:

    从我的想法来看,我的程序在文件删除操作期间正在使用这个文件,所以它不能被删除。

    没错。

    原因是您的sendToFTP 方法会打开它发送到服务器的文件,但它不会(永远)关闭它。由于文件仍处于打开状态,Windows 不会让应用删除它

    解决方案:修改您的 sendToFTP 方法,使 FileInputStream始终关闭。

    【讨论】:

    • 你是对的!简单的fis.close(); 足以解决我的问题。谢谢你:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多