java - 如何删除fileupload struts2中的.tmp文件

标签 java tomcat file-upload struts2 temporary-files

我在 strtus-2.3.15.3 中使用了 file-upload (common fileuplod)。 我的 .jsp 中有一个表单,其中包含多个字段,其中包含许多差异类型(文本字段、文本区域、隐藏、文件),包括 FILE 和明显的 SUBMIT .

当我通过选择一个文件提交表单并在所有其他字段中输入一些文本时,它生成的 .tmp 文件位于提及的临时文件夹中。将我的文件上传到我的文件夹后,只有与文件字段相关的 .tmp 文件将被删除,但其余 .tmp(大小为 1kb)文件仍保留为 .

List items = upload.parseRequest(servletRequest); 

下面代码中的这一行为所有具有某些值的字段生成 .tmp 文件(如果您没有在文本字段中输入任何文本,它不会生成)。

MonitoredMultiPartRequest.java :

public void parse(HttpServletRequest servletRequest, String saveDir)
            throws IOException
    {

        System.setProperty("java.io.tmpdir", "D:\\ankit");

        UploadListener listener = new UploadListener(servletRequest);
        // Create a factory for disk-based file items
        FileItemFactory factory = new MonitoredDiskFileItemFactory(listener);
        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);

    }

MonitoredDiskFileItemFactory:

public class MonitoredDiskFileItemFactory extends DiskFileItemFactory
{
    HttpServletRequest request;

    public MonitoredDiskFileItemFactory(OutputStreamListener listener, HttpServletRequest request)
    {
        this.listener = null;
        this.listener = listener;
        this.request = request;
        setTrackers();
    }

    public void setTrackers()
    {
        FileCleaningTracker fileCleaningTracker = FileCleanerCleanup.getFileCleaningTracker(request.getServletContext());
        File repository = new File(System.getProperty("java.io.tmpdir"));
        DiskFileItemFactory factory = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, repository);
        factory.setFileCleaningTracker(fileCleaningTracker);
        super.setFileCleaningTracker(fileCleaningTracker);
        super.setRepository(repository);
    }

    public MonitoredDiskFileItemFactory(int sizeThreshold, File repository, OutputStreamListener listener)
    {
        super(sizeThreshold, repository);
        this.listener = null;
        this.listener = listener;
    }

    public FileItem createItem(String fieldName, String contentType, boolean isFormField, String fileName)
    {
        MonitoredDiskFileItem result = new MonitoredDiskFileItem(fieldName, contentType, isFormField, fileName, getSizeThreshold(), getRepository(), listener);
        FileCleaningTracker tracker = getFileCleaningTracker();
        if (tracker != null)
        {
            tracker.track(result.getTempFileOfDistFileItem(), result);
        }

        return result;
    }

    private OutputStreamListener listener;
}

MonitoredDiskFileItem:

public class MonitoredDiskFileItem extends DiskFileItem
{

    public MonitoredDiskFileItem(String fieldName, String contentType, boolean isFormField, String fileName, int sizeThreshold, File repository, OutputStreamListener listener)
    {
        super(fieldName, contentType, isFormField, fileName, sizeThreshold, repository);
        mos = null;
        this.listener = listener;
    }

    public OutputStream getOutputStream()
            throws IOException
    {
        if (mos == null)
            mos = new MonitoredOutputStream(super.getOutputStream(), listener);
        return mos;
    }

    public File getTempFileOfDistFileItem()
    {
        return super.getTempFile();
    }

    private MonitoredOutputStream mos;
    private OutputStreamListener listener;
}

上传监听器 :

public class UploadListener implements OutputStreamListener, Serializable
{
    private static final long serialVersionUID = 1L;
    private int totalToRead = 0;
    private int totalBytesRead = 0;
    private int percentDone = 0;
    private int previou_percentDone = 0;
    private long uploadspeed = 0;
    private long starttime;
    private long stTime, EndTime;
    HttpSession session;
    private int count = 0;

    public UploadListener(HttpServletRequest request)
    {
        totalToRead = request.getContentLength();
        session = request.getSession();
    }

    public void start()
    {
        session.setAttribute("percentageDone", 0);
        session.setAttribute("speed", 0);
        starttime = System.currentTimeMillis();
        stTime = starttime;

    }

    public String getMessage()
    {
        return "" + totalBytesRead + " bytes have been read (" + percentDone + "% done)  ";
    }

    public void bytesRead(int bytesRead)
    {
        totalBytesRead = totalBytesRead + bytesRead;

        if (100.00 * totalBytesRead > totalToRead)
        {
            previou_percentDone = percentDone;
            percentDone = (int) Math.round(100.00 * totalBytesRead / totalToRead);
            if (previou_percentDone < percentDone)
            {
                long speed = 0;
                try
                {
                    double TimediffInSecond = (System.currentTimeMillis() - starttime) / 1000;
                    if (TimediffInSecond > 0)
                        speed = Math.round(((totalBytesRead) / TimediffInSecond) / 1048576);
                    else
                        speed = totalBytesRead / 1048576;

                }
                catch (Exception e)
                {
                    System.err.println(e.getMessage());
                }
            }
        }


    }

    public void done()
    {
        EndTime = System.currentTimeMillis();
        session.setAttribute("percentageDone", 100);
        session.setAttribute("speed", 100);
    }

    @Override
    public void error(String message)
    {
        // System.out.println(message);
    }

    public long getUploadspeed()
    {
        return uploadspeed;
    }

    public void setUploadspeed(long uploadspeed)
    {
        this.uploadspeed = uploadspeed;
    }

}

编辑 :

1> 为什么要为字段 (textarea ,hidden,textfield) 生成此 .tmp 文件。 我们怎样才能防止这种情况发生?

2> 我想停止为所有字段生成 .tmp 文件,type='file'(文件字段)除外。

3> 否则,我该如何删除所有 .tmp 文件?

最佳答案

为此您不需要 Commons 库,也不需要 Servlet。

您正在使用 Struts2,所以不要重新发明轮子并使用 ActionsInterceptors

您可以找到 upload multiple files with Struts2 in this exhaustive answer 的代码,并通过 creating a custom object in this other answer 进行了一些改进.

我觉得有必要链接this nice answer from BalusC在谈论通过 Servlet 上传文件时也是如此。


让我们来回答您的具体问题:您正在使用 MonitoredDiskFileItemFactory,(您没有指定网络上正在增长的众多实现中的哪一个,但很可能它是 ->) 标准的子类 org.apache.commons.fileupload.disk.DiskFileItemFactory .

在 JavaDoc 中有很好的解释:

This implementation creates FileItem instances which keep their content either in memory, for smaller items, or in a temporary file on disk, for larger items. The size threshold, above which content will be stored on disk, is configurable, as is the directory in which temporary files will be created.

If not otherwise configured, the default configuration values are as follows:

  • Size threshold is 10KB.
  • Repository is the system default temp directory, as returned by System.getProperty("java.io.tmpdir").

NOTE: Files are created in the system default temp directory with predictable names. This means that a local attacker with write access to that directory can perform a TOUTOC attack to replace any uploaded file with a file of the attackers choice. The implications of this will depend on how the uploaded file is used but could be significant. When using this implementation in an environment with local, untrusted users, setRepository(File) MUST be used to configure a repository location that is not publicly writable. In a Servlet container the location identified by the ServletContext attribute javax.servlet.context.tempdir may be used.

Temporary files, which are created for file items, should be deleted later on. The best way to do this is using a FileCleaningTracker, which you can set on the DiskFileItemFactory. However, if you do use such a tracker, then you must consider the following: Temporary files are automatically deleted as soon as they are no longer needed. (More precisely, when the corresponding instance of File is garbage collected.) This is done by the so-called reaper thread, which is started automatically when the class FileCleaner is loaded. It might make sense to terminate that thread, for example, if your web application ends. See the section on "Resource cleanup" in the users guide of commons-fileupload.

来自 Commons FileUpload Documantation

Resource cleanup

This section applies only, if you are using the DiskFileItem. In other words, it applies, if your uploaded files are written to temporary files before processing them.

Such temporary files are deleted automatically, if they are no longer used (more precisely, if the corresponding instance of java.io.File is garbage collected. This is done silently by the org.apache.commons.io.FileCleaner class, which starts a reaper thread.

This reaper thread should be stopped, if it is no longer needed. In a servlet environment, this is done by using a special servlet context listener, called FileCleanerCleanup. To do so, add a section like the following to your web.xml:

<web-app>
  ...
  <listener>
    <listener-class>
      org.apache.commons.fileupload.servlet.FileCleanerCleanup
    </listener-class>
  </listener>
  ...
</web-app>

Creating a DiskFileItemFactory

The FileCleanerCleanup provides an instance of org.apache.commons.io.FileCleaningTracker. This instance must be used when creating a org.apache.commons.fileupload.disk.DiskFileItemFactory. This should be done by calling a method like the following:

public static DiskFileItemFactory newDiskFileItemFactory(ServletContext context
                                                           , File repository) {
    FileCleaningTracker fileCleaningTracker
          = FileCleanerCleanup.getFileCleaningTracker(context);
    DiskFileItemFactory factory
          = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD,
                                      repository);
    factory.setFileCleaningTracker(fileCleaningTracker);
    return factory;
}

Disabling cleanup of temporary files

To disable tracking of temporary files, you may set the FileCleaningTracker to null. Consequently, created files will no longer be tracked. In particular, they will no longer be deleted automatically.

然后你可以:

  1. 设置更高的阈值,将所有内容保存在内存中,而不是使用临时文件,或者
  2. 遵循 Apache 准则正确删除不再需要的临时文件

关于java - 如何删除fileupload struts2中的.tmp文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19543422/

相关文章:

java - 使用java编辑html页面

java - 媒体类型 "multipart/form-data"没有可用的 MessageBodyWriter

asp.net-mvc - 从mvc中的FormCollection值中获取Fileupload值

java - WSDL 包含中的 XSD 文件路径错误

java - 无法设置 cookie 的值

java - 如何使用 Java 标准 API 从字符串中获取特定数据?

performance - 从 tomcat 响应时间计算吞吐量

java - GWT 和不可重现的 503 错误

asp.net-mvc - dropzonejs 多文件上传无法按预期工作

android - 用phonegap上传媒体文件,Android