How to delete .tmp file in fileupload struts2

2019-02-20 12:58发布

I have used file-upload (common fileuplod) in strtus-2.3.15.3 . There is one Form in my .jsp with multiple field with many diff type(textfield,textarea,hidden,file) including FILE and obvious 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 . 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 .

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) .

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

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 :

1> Why this .tmp file is generated for fields (textarea ,hidden,textfield) . How can we prevent this ?

2> i want to stop generating .tmp file for all field except where type='file'(file field) .

3> Otherwise, how can i delete this all .tmp file ?

1条回答
我想做一个坏孩纸
2楼-- · 2019-02-20 13:44

You don't need Commons libraries for this, nor a Servlet.

You are using Struts2, so don't reinvent the wheel and use Actions and Interceptors.

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.

I feel the need to link this nice answer from BalusC too, when talking about fileUpload through Servlet.


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.

In the JavaDoc it is well explained that:

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.

From 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.

Then you can:

  1. set an higher threeshold, to keep everything in memory instead that using temporary files, or
  2. follow Apache guidelines to properly wipe temporary files when they're not needed anymore.
查看更多
登录 后发表回答