简体   繁体   English

如何在fileupload struts2中删除.tmp文件

[英]How to delete .tmp file in fileupload struts2

I have used file-upload (common fileuplod) in strtus-2.3.15.3 . 我在strtus-2.3.15.3使用了file-upload (common fileuplod)。 There is one Form in my .jsp with multiple field with many diff type(textfield,textarea,hidden,file) including FILE and obvious SUBMIT . 我的.jsp有一个Form有多个字段,有很多diff类型(textfield,textarea,hidden,file),包括FILE和明显的SUBMIT

When i submit form by selecting one file and enter some text in all other field its generated .tmp file in mention temp folder . 当我通过选择一个文件提交表单并在所有其他字段中输入一些文本时,它会在提到临时文件夹中生成.tmp文件。 Only .tmp file related to file field is going to delete after uploading my file to myfolder but rest of .tmp (with 1kb size) file is remaing as its . 将我的文件上传到myfolder后,只有与文件字段相关的.tmp文件才会被删除,但其余的.tmp (1kb大小)文件将被重新保存。

List items = upload.parseRequest(servletRequest); 

This line in below code generate .tmp file for all field which have some value (if you do not enter any text in text field it not generated) . 下面代码中的这一行为所有具有一定值的字段生成.tmp文件(如果未在文本字段中输入任何文本,则不生成)。

MonitoredMultiPartRequest.java : 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 : 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 : 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;
}

UploadListener : UploadListener

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;
    }

}

EDIT : EDIT

1> Why this .tmp file is generated for fields (textarea ,hidden,textfield) . 1>为什么为字段(textarea,hidden,textfield)生成此.tmp文件。 How can we prevent this ? 我们怎么能防止这种情况?

2> i want to stop generating .tmp file for all field except where type='file' (file field) . 2>我想停止为所有字段生成.tmp文件,除了type='file' (文件字段)。

3> Otherwise, how can i delete this all .tmp file ? 3>否则,如何删除所有.tmp文件?

You don't need Commons libraries for this, nor a Servlet. 你不需要Commons库,也不需要Servlet。

You are using Struts2, so don't reinvent the wheel and use Actions and Interceptors . 您正在使用Struts2,因此不要重新发明轮子并使用动作拦截器

You can find the code to upload multiple files with Struts2 in this exhaustive answer , and a little improvement by creating a custom object in this other answer . 您可以在这个详尽的答案中找到使用Struts2上传多个文件的代码,并通过在另一个答案中创建自定义对象来进行一些改进。

I feel the need to link this nice answer from BalusC too, when talking about fileUpload through Servlet. 当我通过Servlet谈论fileUpload时,我觉得有必要将这个来自BalusC的好答案联系起来。


Let's come to your specific question: you are using a MonitoredDiskFileItemFactory , (you didn't specified which of the many implementations growing on the web, but it is likely that it is ->) a Subclass of the standard org.apache.commons.fileupload.disk.DiskFileItemFactory . 让我们来讨论您的具体问题:您正在使用MonitoredDiskFileItemFactory ,(您没有指定在Web上增长的许多实现中的哪一个,但很可能是 - >)标准org.apache.commons.fileupload.disk.DiskFileItemFactory的子类org.apache.commons.fileupload.disk.DiskFileItemFactory

In the JavaDoc it is well explained that: 在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. 此实现创建了FileItem实例,这些实例将其内容保留在内存中 ,较小的项目或磁盘上的临时文件中 ,以用于较大的项目。 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. 大小阈值为10KB。
  • Repository is the system default temp directory, as returned by System.getProperty("java.io.tmpdir") . 存储库是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. 这意味着对该目录具有写访问权限的本地攻击者可以执行TOUTOC攻击,以使用攻击者选择的文件替换任何上载的文件。 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. 在具有本地不受信任的用户的环境中使用此实现时,必须使用setRepository(File)来配置不可公开写入的存储库位置。 In a Servlet container the location identified by the ServletContext attribute javax.servlet.context.tempdir may be used. 在Servlet容器中,可以使用ServletContext属性javax.servlet.context.tempdir标识的位置。

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 . 执行此操作的最佳方法是使用FileCleaningTracker ,您可以在DiskFileItemFactory上设置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. (更确切地说,当相应的File实例被垃圾收集时。)这是由所谓的reaper线程完成的,它在加载类FileCleaner时自动启动。 It might make sense to terminate that thread, for example, if your web application ends. 例如,如果您的Web应用程序结束,则终止该线程可能是有意义的。 See the section on "Resource cleanup" in the users guide of commons-fileupload. 请参阅commons-fileupload用户指南中的“资源清理”部分。

From Commons FileUpload Documantation 来自Commons FileUpload Documantation

Resource cleanup 资源清理

This section applies only, if you are using the DiskFileItem . 如果您使用的是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. 如果不再使用这些临时文件,则会自动删除这些临时文件(更准确地说,如果相应的java.io.File实例是垃圾收集的。这是由org.apache.commons.io.FileCleaner类静默完成的,它启动收割者的线程。

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 . 在servlet环境中,这是通过使用名为FileCleanerCleanup的特殊servlet上下文侦听器来FileCleanerCleanup To do so, add a section like the following to your web.xml: 为此,请在web.xml中添加如下部分:

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

Creating a DiskFileItemFactory 创建DiskFileItemFactory

The FileCleanerCleanup provides an instance of org.apache.commons.io.FileCleaningTracker . FileCleanerCleanup提供了org.apache.commons.io.FileCleaningTracker的实例。 This instance must be used when creating a org.apache.commons.fileupload.disk.DiskFileItemFactory . 创建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. 要禁用对临时文件的跟踪,可以将FileCleaningTracker设置为null。 Consequently, created files will no longer be tracked. 因此,将不再跟踪创建的文件。 In particular, they will no longer be deleted automatically. 特别是,它们将不再自动删除。

Then you can: 那么你也能:

  1. set an higher threeshold, to keep everything in memory instead that using temporary files, or 设置更高的threeshold,将所有内容保存在内存中,而不是使用临时文件,或
  2. follow Apache guidelines to properly wipe temporary files when they're not needed anymore. 遵循Apache准则,在不再需要临时文件正确擦除它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM