`
113.com
  • 浏览: 81162 次
  • 来自: 广州
社区版块
存档分类
最新评论

FileUpload 文件上传说明

    博客分类:
  • JSP
阅读更多

这是传统的API,也就是旧的。

Servlets and Portlets

Starting with version 1.1, FileUpload supports file upload requests in both servlet and portlet environments. The usage is almost identical in the two environments, so the remainder of this document refers only to the servlet environment.

If you are building a portlet application, the following are the two distinctions you should make as you read this document:

  • Where you see references to the ServletFileUpload class, substitute the PortletFileUpload class.
  • Where you see references to the HttpServletRequest class, substitute the ActionRequest class.

Parsing the request

Before you can work with the uploaded items, of course, you need to parse the request itself. Ensuring that the request is actually a file upload request is straightforward, but FileUpload makes it simplicity itself, by providing a static method to do just that.

// Check that we have a file upload requestboolean isMultipart =ServletFileUpload.isMultipartContent(request);

Now we are ready to parse the request into its constituent items.

The simplest case

The simplest usage scenario is the following:

  • Uploaded items should be retained in memory as long as they are reasonably small.
  • Larger items should be written to a temporary file on disk.
  • Very large upload requests should not be permitted.
  • The built-in defaults for the maximum size of an item to be retained in memory, the maximum permitted size of an upload request, and the location of temporary files are acceptable.

Handling a request in this scenario couldn't be much simpler:

// Create a factory for disk-based file itemsFileItemFactory factory =newDiskFileItemFactory();// Configure a repository (to ensure a secure temp location is used)ServletContext servletContext =this.getServletConfig().getServletContext();File repository =(File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);// Create a new file upload handlerServletFileUpload upload =newServletFileUpload(factory);// Parse the requestList<FileItem> items = upload.parseRequest(request);

That's all that's needed. Really!

The result of the parse is a List of file items, each of which implements the FileItem interface. Processing these items is discussed below.

Exercising more control

If your usage scenario is close to the simplest case, described above, but you need a little more control, you can easily customize the behavior of the upload handler or the file item factory or both. The following example shows several configuration options:

// Create a factory for disk-based file itemsDiskFileItemFactory factory =newDiskFileItemFactory();// Set factory constraints
factory.setSizeThreshold(yourMaxMemorySize);
factory.setRepository(yourTempDirectory);// Create a new file upload handlerServletFileUpload upload =newServletFileUpload(factory);// Set overall request size constraint
upload.setSizeMax(yourMaxRequestSize);// Parse the requestList<FileItem> items = upload.parseRequest(request);

Of course, each of the configuration methods is independent of the others, but if you want to configure the factory all at once, you can do that with an alternative constructor, like this:

// Create a factory for disk-based file itemsDiskFileItemFactory factory =newDiskFileItemFactory(yourMaxMemorySize, yourTempDirectory);

Should you need further control over the parsing of the request, such as storing the items elsewhere - for example, in a database - you will need to look into customizing FileUpload.

Processing the uploaded items

Once the parse has completed, you will have a List of file items that you need to process. In most cases, you will want to handle file uploads differently from regular form fields, so you might process the list like this:

// Process the uploaded itemsIterator<FileItem> iter = items.iterator();while(iter.hasNext()){
    FileItem item = iter.next();

    if(item.isFormField()){
        processFormField(item);
    }else{
        processUploadedFile(item);
    }}

For a regular form field, you will most likely be interested only in the name of the item, and its String value. As you might expect, accessing these is very simple.

// Process a regular form fieldif(item.isFormField()){
    String name = item.getFieldName();
    String value = item.getString();
    ...}

For a file upload, there are several different things you might want to know before you process the content. Here is an example of some of the methods you might be interested in.

// Process a file uploadif(!item.isFormField()){
    String fieldName = item.getFieldName();
    String fileName = item.getName();
    String contentType = item.getContentType();
    boolean isInMemory = item.isInMemory();
    long sizeInBytes = item.getSize();
    ...}

With uploaded files, you generally will not want to access them via memory, unless they are small, or unless you have no other alternative. Rather, you will want to process the content as a stream, or write the entire file to its ultimate location. FileUpload provides simple means of accomplishing both of these.

// Process a file uploadif(writeToFile){
    File uploadedFile =newFile(...);
    item.write(uploadedFile);}else{
    InputStream uploadedStream = item.getInputStream();
    ...
    uploadedStream.close();}

Note that, in the default implementation of FileUpload, write() will attempt to rename the file to the specified destination, if the data is already in a temporary file. Actually copying the data is only done if the the rename fails, for some reason, or if the data was in memory.

If you do need to access the uploaded data in memory, you need simply call the get() method to obtain the data as an array of bytes.

// Process a file upload in memorybyte[] data = item.get();...

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:

publicstaticDiskFileItemFactory newDiskFileItemFactory(ServletContext context,
                                                         File repository){
    FileCleaningTracker fileCleaningTracker
        =FileCleanerCleanup.getFileCleaningTracker(context);
    DiskFileItemFactory factory
        =newDiskFileItemFactory(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.

Interaction with virus scanners

Virus scanners running on the same system as the web container can cause some unexpected behaviours for applications using FileUpload. This section describes some of the behaviours that you might encounter, and provides some ideas for how to handle them.

The default implementation of FileUpload will cause uploaded items above a certain size threshold to be written to disk. As soon as such a file is closed, any virus scanner on the system will wake up and inspect it, and potentially quarantine the file - that is, move it to a special location where it will not cause problems. This, of course, will be a surprise to the application developer, since the uploaded file item will no longer be available for processing. On the other hand, uploaded items below that same threshold will be held in memory, and therefore will not be seen by virus scanners. This allows for the possibility of a virus being retained in some form (although if it is ever written to disk, the virus scanner would locate and inspect it).

One commonly used solution is to set aside one directory on the system into which all uploaded files will be placed, and to configure the virus scanner to ignore that directory. This ensures that files will not be ripped out from under the application, but then leaves responsibility for virus scanning up to the application developer. Scanning the uploaded files for viruses can then be performed by an external process, which might move clean or cleaned files to an "approved" location, or by integrating a virus scanner within the application itself. The details of configuring an external process or integrating virus scanning into an application are outside the scope of this document.

Watching progress

If you expect really large file uploads, then it would be nice to report to your users, how much is already received. Even HTML pages allow to implement a progress bar by returning a multipart/replace response, or something like that.

Watching the upload progress may be done by supplying a progress listener:

//Create a progress listenerProgressListener progressListener =newProgressListener(){
   publicvoid update(long pBytesRead,long pContentLength,int pItems){
       System.out.println("We are currently reading item "+ pItems);
       if(pContentLength ==-1){
           System.out.println("So far, "+ pBytesRead +" bytes have been read.");
       }else{
           System.out.println("So far, "+ pBytesRead +" of "+ pContentLength
                              +" bytes have been read.");
       }
   }};
upload.setProgressListener(progressListener);

Do yourself a favour and implement your first progress listener just like the above, because it shows you a pitfall: The progress listener is called quite frequently. Depending on the servlet engine and other environment factory, it may be called for any network packet! In other words, your progress listener may become a performance problem! A typical solution might be, to reduce the progress listeners activity. For example, you might emit a message only, if the number of megabytes has changed:

//Create a progress listenerProgressListener progressListener =newProgressListener(){
   privatelong megaBytes =-1;
   publicvoid update(long pBytesRead,long pContentLength,int pItems){
       long mBytes = pBytesRead /1000000;
       if(megaBytes == mBytes){
           return;
       }
       megaBytes = mBytes;
       System.out.println("We are currently reading item "+ pItems);
       if(pContentLength ==-1){
           System.out.println("So far, "+ pBytesRead +" bytes have been read.");
       }else{
           System.out.println("So far, "+ pBytesRead +" of "+ pContentLength
                              +" bytes have been read.");
       }
   }};


http://commons.apache.org/proper/commons-fileupload/using.html










 

这是新的API,也就是基于Streaming

Why Streaming?

The traditional API, which is described in the User Guide, assumes, that file items must be stored somewhere, before they are actually accessable by the user. This approach is convenient, because it allows easy access to an items contents. On the other hand, it is memory and time consuming.

The streaming API allows you to trade a little bit of convenience for optimal performance and and a low memory profile. Additionally, the API is more lightweight, thus easier to understand.

How it works

Again, the FileUpload class is used for accessing the form fields and fields in the order, in which they have been sent by the client. However, the FileItemFactory is completely ignored.

Parsing the request

First of all, do not forget to ensure, that a request actually is a a file upload request. This is typically done using the same static method, which you already know from the traditional API.

// Check that we have a file upload request
boolean isMultipart =ServletFileUpload.isMultipartContent(request);

Now we are ready to parse the request into its constituent items. Here's how we do it:

// Create a new file upload handler
ServletFileUpload upload =newServletFileUpload();

// Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while(iter.hasNext()){
    FileItemStream item = iter.next();
    String name = item.getFieldName();
    InputStream stream = item.openStream();
    if(item.isFormField()){
        System.out.println("Form field "+ name +" with value "
            +Streams.asString(stream)+" detected.");
    }else{
        System.out.println("File field "+ name +" with file name "
            + item.getName()+" detected.");
        // Process the input stream
        ...
    }
}

That's all that's needed. Really!



分享到:
评论

相关推荐

    fileupload插件 上传文件自带进度条

    总的来说,fileupload插件是一个强大的文件上传解决方案,它通过提供进度条功能和自定义限制,提高了用户在上传文件过程中的体验。同时,它也展示了现代Web技术如何与后端服务紧密结合,实现高效、安全的文件上传...

    用FileUpload控件上传文件到数据库

    下面通过具体的代码示例来说明如何使用ASP.NET中的`FileUpload`控件实现文件上传功能。 ```csharp try { string name = FileUpload1.FileName; // 获取上传文件的名称 string size = FileUpload1.PostedFile....

    C#Fileupload上传控件上传任意大小的文件

    3. **处理大文件上传**:对于大文件,我们可能需要分块上传以避免内存溢出。可以通过创建一个循环,每次读取文件的一部分,然后写入服务器的临时目录。使用Stream类可以有效地处理这个过程。 以下是一个简单的C#...

    Serlvet_fileupload文件上传功能,导入直接使用

    在本篇文章中,我们将深入探讨如何利用Servlet_fileupload实现文件上传功能,并进行详细步骤说明。 **一、理解HTTP多部分数据** 在HTML表单中,如果设置了`enctype="multipart/form-data"`,那么表单提交的数据将...

    实现文件上传的fileupload

    "实现文件上传的fileupload"这个项目旨在提供一个简单易用的解决方案,让用户能够方便地上传文件,甚至可以支持多文件同时上传。这样的功能在很多场景下都非常实用,比如用户在社交媒体分享照片、在云存储服务上传...

    FileUpload+DWR 多文件上传实例

    原理: FileUpload实现上传功能, UploadListener 监听上传进度, DWR push (Reverse Ajax) 进度信息并更新页面, 实现无刷新多文件上传 运行环境: Tomcat 5/6 测试通过 说明:累计上传文件不超过10M(可以更改...

    jsp 文件上传 fileupload

    【标题】"jsp 文件上传 fileupload" 描述的是一个基于JSP实现的文件上传系统,该系统具备文件管理功能,并且允许用户进行登录操作。在系统中,管理员可以通过/admin.jsp页面进行管理,登录的用户名和密码都设定为...

    fileupload commons-io上传文件

    以上就是关于“fileupload commons-io上传文件”这一主题的详细说明,涵盖了Apache Commons IO和FileUpload库在文件上传中的应用,以及如何使用这两个库实现文件上传功能的基本步骤。在实际开发中,根据具体需求,还...

    FileUpload整理过多选文件上传.zip

    标题中的"FileUpload整理过多选文件上传.zip"表明这是一个关于批量文件上传技术的资源包。在这个压缩包中,开发者或者学习者将找到有关如何实现一次选择并上传多个文件的解决方案。描述提到的"支持多文件上传,打破...

    文件上传 组件fileupload

    文件上传组件FileUpload的核心功能包括: 1. **多文件选择**:用户可以通过选择多个文件来一次性上传,提高上传效率。 2. **进度条显示**:在上传过程中,提供文件上传进度的可视化反馈,提升用户体验。 3. **文件...

    FileUpload.rar文件上传(所以文件)

    内含文档说明和demo演示!~ 用struts的commons-fileUpload.jar实现文件上传,所以文件都可以,并另加图片预览功能!~ 采用简单常用jsp+servlet实现,同样对使用struts实现上传进行了说明~

    利用commons-fileupload组件实现文件上传-实例

    本文将详细介绍如何利用这个组件实现文件上传,并通过一个简单的实例来说明。 Apache Commons FileUpload组件是Apache Commons项目的一部分,它为Servlet环境提供了处理多部分HTTP请求(即文件上传请求)的功能。多...

    vuebase64fileupload利用Vuejs将上传文件作为base64datauris

    在现代Web应用中,文件上传是一个常见的功能,而将文件转换为Base64编码的数据URI(data URI scheme)则有助于实现异步上传、预览文件等需求。`vue-base64-file-upload`是一个专为Vue.js设计的组件,它简化了这一...

    bootstrap 文件上传组件 fileinput 实现文件批量上传

    Bootstrap文件上传组件FileInput是一款强大的前端文件上传工具,尤其适合于需要实现文件批量上传的场景。这个组件基于Bootstrap框架,提供了美观的用户界面和丰富的功能,使得文件上传操作变得直观且易于实现。以下...

    Java上传的通用代码包括(jspsmartupload,fileupload)

    "Java上传的通用代码包括(jspsmartupload, fileupload)"这个标题提到的两个库——JSPSmartUpload和FileUpload,都是用于处理文件上传的Java库,它们为开发者提供了方便的API来实现这一功能。 1. **JSPSmartUpload**...

    文件上传绕过思路总结 - 先知社区1

    以下是对文件上传绕过思路的详细说明: 1. **Accept-Encoding 改变编码类型**: WAF通常会检查HTTP请求中的`Accept-Encoding`头,该头用于指示客户端接受的编码类型。通过改变或添加不常见的编码类型,如`gzip`、`...

    commons-fileupload实现jsp上传实例(源码).rar

    【标题】:基于Apache Commons FileUpload的JSP文件上传实现 Apache Commons FileUpload是一个非常流行的Java库,专门用于处理HTTP请求中的多部分数据,也就是通常所说的文件上传功能。在JSP(JavaServer Pages)中...

    上传下载仿163网盘无刷新文件上传 for Jsp-fileupload-jsp.rar

    "仿163网盘无刷新文件上传 for Jsp_fileupload_jsp.rar" 是一个压缩包,内含一系列JSP和Java文件,构成了一个完整的文件上传系统。该系统允许用户在不刷新页面的情况下上传文件,实现了类似163网盘的用户体验。通过...

    ASP.NET多文件上传,单文件上传,很好用【源代码】

    在ASP.NET中,文件上传主要通过`&lt;asp:FileUpload&gt;`控件实现。用户可以选择本地计算机上的文件,并将其上传到服务器。要实现单文件上传,你需要在HTML部分添加FileUpload控件,然后在服务器端处理文件的接收。C#代码...

Global site tag (gtag.js) - Google Analytics