1

file-uploadstrtus-2.3.15.3. 我的表单中.jsp有多个字段,其中包含许多差异类型(文本字段、文本区域、隐藏、文件),包括FILE和明显SUBMIT的 .

当我通过选择一个文件提交表单并在所有其他字段中输入一些文本时,它.tmp在提及临时文件夹中生成的文件。将我的文件上传到 myfolder 后,只有.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;
}

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> 为什么.tmp为字段(textarea,hidden,textfield)生成此文件。我们怎样才能防止这种情况发生?

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

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

4

1 回答 1

4

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

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

您可以在此详尽答案中找到使用 Struts2 上传多个文件的代码,并通过在此其他答案中创建自定义对象进行一些改进。

在谈论通过 Servlet 进行文件上传时,我觉得也有必要将BalusC 的这个不错的答案联系起来。


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

在 JavaDoc 中很好地解释了:

此实现创建FileItem实例,这些实例将其内容保存在内存中,用于较小的项目,或保存在磁盘上的临时文件中,用于较大的项目。将内容存储在磁盘上的大小阈值是可配置的,将在其中创建临时文件的目录也是如此。

如果没有另外配置,默认配置值如下:

  • 大小阈值为 10KB。
  • Repository 是系统默认的临时目录,由 System.getProperty("java.io.tmpdir").

注意:文件是在系统默认临时目录中创建的,具有可预测的名称。这意味着对该目录具有写访问权限的本地攻击者可以执行TOUTOC攻击,用攻击者选择的文件替换任何上传的文件。其影响将取决于上传文件的使用方式,但可能很重要。在具有本地、不受信任的用户的环境中使用此实现时, setRepository(File)必须用于配置不可公开写入的存储库位置。在 Servlet 容器中, javax.servlet.context.tempdir可以使用由 ServletContext 属性标识的位置。

为文件项创建的临时文件应稍后删除。最好的方法是使用FileCleaningTracker,您可以在DiskFileItemFactory. 但是,如果您确实使用了这样的跟踪器,那么您必须考虑以下几点: 临时文件在不再需要时会自动删除。(更准确地说,当相应的 File 实例被垃圾回收时。)这是由所谓的 reaper 线程完成的,该线程在加载 FileCleaner 类时自动启动。例如,如果您的 Web 应用程序结束,终止该线程可能是有意义的。请参阅 commons-fileupload 的用户指南中的“资源清理”部分。

来自Commons FileUpload 文档

资源清理

本节仅适用于您使用DiskFileItem. 换句话说,它适用于您上传的文件在处理之前写入临时文件的情况。

如果不再使用这些临时文件(更准确地说,如果相应的实例java.io.File被垃圾收集,则这些临时文件会被自动删除。这是由 org.apache.commons.io.FileCleaner启动一个收割线程的类静默完成的。

如果不再需要,应该停止这个 reaper 线程。在 servlet 环境中,这是通过使用一个特殊的 servlet 上下文侦听器来完成的,称为FileCleanerCleanup. 为此,请在 web.xml 中添加如下部分:

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

创建 DiskFileItemFactory

提供FileCleanerCleanup了一个 org.apache.commons.io.FileCleaningTracker. 创建 org.apache.commons.fileupload.disk.DiskFileItemFactory. 这应该通过调用如下方法来完成:

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

禁用清理临时文件

要禁用对临时文件的跟踪,您可以将 设置 FileCleaningTracker为 null。因此,将不再跟踪创建的文件。特别是,它们将不再被自动删除。

那么你也能:

  1. 设置更高的三分位数,将所有内容保存在内存中,而不是使用临时文件,或者
  2. 遵循 Apache 指南在不再需要临时文件时正确擦除它们。
于 2013-10-23T14:19:09.400 回答