【问题标题】:Webapplication: Delete files during runtimeWeb应用程序:在运行时删除文件
【发布时间】:2013-08-26 10:05:02
【问题描述】:

我正在开发一个网络应用程序(用于手机)。有一个 xhtml 页面,我想在其中显示一张图片,该图片本地存储在我的硬盘上(例如:D:\pictures\test.jpg)。 由于浏览器在位于本地硬盘驱动器上时会阻止图像,所以我在我的 javabean 中编写了一个方法,当用户进入 xhtml 页面时,将存储在 localHD 上的图片复制到 webApp 目录。用户离开页面后,应删除 webapp 内的复制文件。 所以当我运行我的应用程序时,复制工作完美,图片显示正确。但是,当文件应该被删除时,我会收到以下错误消息:

java.nio.file.FileSystemException: D:\WebAppPath\src\main\webapp\resources\pics\test.jpg: 无法访问该进程,因为该文件正被另一个进程使用。

奇怪的是,在停止并重新启动应用程序后,如果它仍在 webApp 目录中,我可以删除相同的图像。 (但只有一次;重新复制后,我再次收到错误消息。)

另外,如果我想手动删除文件,通过使用 Windows 资源管理器,我会收到无法删除文件的错误消息,因为它由 Java(TM) Platform SE Binary 使用。

所以要删除文件(手动或通过 bean),我必须等待应用程序重新启动,这当然不是最终用户可接受的解决方案。

我正在使用带有 Primefaces 和 Primefaces Mobile 组件的 JSF2.0。我的 IDE 是 Netbeans,我使用 Spring Webflow 框架在 xhtml 页面之间导航和触发操作/方法。

这是我的 JavaBean 中复制方法的代码:

    public void copyFotoToLocalhost() {
    if (fotoList.size() > 0) {
        for (int i = 0; i < fotoList.size(); i++) {
            Foto tempPic = fotoList.get(i);
            String tempItemName = tempPic.getItemName();
            String originalFile = "D:\\localFilepath\\" + tempItemName;
            String tempFileName = "D:\\WebAppPath\\src\\main\\webapp\\resources\\pics\\" + tempItemName;
            File existTest = new File(tempFileName);

            if (existTest.exists() == false) {
                try {
                    File orFile = new File(originalFile);
                    File tempFile = new File(tempFileName);


                    InputStream in = new FileInputStream(orFile);
                    OutputStream out = new FileOutputStream(tempFile);

                    byte[] buf = new byte[8192];
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    in.close();
                    out.close();

                    tempFile.setWritable(true);

                    System.out.println("File copied.");
                } catch (FileNotFoundException ex) {
                    System.out.println(ex.getMessage() + " in the specified directory.");
                    System.exit(0);
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
    }
}

这里是删除方法的代码:

public void deleteFotos() {
        if (fotoList.size() > 0) {
            for (int i = 0; i < fotoList.size(); i++) {
                Foto tempPic = fotoList.get(i);
                String tempItemName = tempPic.getItemName();

                Path tempLocation = Paths.get("D:\\webAppPath\\src\\main\\webapp\\resources\\pics\\" + tempItemName);
                fotoList.remove(i);
                i--;
                try {
                    Files.deleteIfExists(tempLocation);
                    System.out.println("sucessfully deleted" + tempPic.getItemName());
                } catch (IOException ex) {
                    Logger.getLogger(WundDokuBean.class.getName()).log(Level.SEVERE, null, ex);
                    System.out.println("Fail @ " + tempPic.getItemName());
                }

            }
            fotoList.clear();
        }

你有什么想法,如何解决这个问题?

希望您能理解我的问题,如果不明白,请告诉我您需要哪些信息,我会尽力提供。

【问题讨论】:

    标签: java spring jsf primefaces xhtml


    【解决方案1】:

    有一个 xhtml 页面,我想在其中显示一张图片,该图片本地存储在我的硬盘上(例如:D:\pictures\test.jpg)。由于浏览器在图像位于本地硬盘驱动器时会阻止图像 (...)

    我想首先澄清一个概念上的误解:您似乎希望当浏览器不会阻止它时它会正常工作。这是完全不真实的。您似乎期望图像在 HTML 输出中是内联的。不,它们是独立于 HTML 页面单独下载的。如果您继续使用本地磁盘文件系统路径,那么只有当您的网页访问者在 exactly 他们的磁盘文件系统。实际上,显然并非如此。只有当网络浏览器和网络服务器都在同一台机器上运行时,它才会起作用。


    回到你无法删除文件的具体问题,这是因为servletcontainer通常将文件锁定在扩展的WAR文件夹中。我无法说出确切的原因,但这在这里无关紧要,因为整个方法无论如何都是错误的。当部署的 WAR 文件没有在磁盘文件系统上展开,而是在服务器的内存中展开时,这种方法会失败。此外,硬编码特定于环境的磁盘文件系统路径也是一个坏主意。每次更改环境时,您都需要编辑、重写、重新编译、重建整个 WAR。换句话说,你的 web 应用是不可移植的。

    您需要将文件保留在原来的位置,并通过真实 URL 公开它们。这可以通过两种一般方式实现:

    1. 在服务器配置中添加一个虚拟主机,指向D:\localFilepath\。如何实现取决于使用的服务器。您没有告诉任何有关使用的服务器品牌/版本的信息,但使用 Spring 表明您无法使用完整的 Java EE 堆栈,并且可能使用准系统 JSP/Servlet 容器,例如 Tomcat。在这种情况下,只需将以下行添加到其/conf/server.xml

      <Context docBase="D:\localFilepath" path="/fotos" />
      

      这样,http://localhost:8080/fotos/* 就可以使用它们。


    2. 创建一个 servlet,它从 D:\localFilepath 读取文件并写入 HTTP 响应。使用 Servlet 3.0 和 Java 7 真的是轻而易举。这是一个启动示例(为简洁起见,省略了 nullchecks/file-exist-checks/doHead()/caching/resuming):

      @WebServlet("/fotos/*")
      public class FotosServlet extends HttpServlet {
      
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletExcpetion, IOException {
              File file = new File("D:/localFilepath", request.getPathInfo().substring(1));
              response.setHeader("Content-Type", getServletContext().getMimeType(file.getName()));
              response.setHeader("Content-Length", String.valueOf(file.length()));
              Files.copy(file.toPath(), response.getOutputStream());
          }
      
      }
      

      基本上就是这样。这样他们就可以在http://localhost:8080/contextname/fotos/* 上使用。

    【讨论】:

      猜你喜欢
      • 2011-08-25
      • 1970-01-01
      • 1970-01-01
      • 2011-07-31
      • 1970-01-01
      • 1970-01-01
      • 2013-07-30
      • 1970-01-01
      • 2014-07-01
      相关资源
      最近更新 更多