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

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!



分享到:
评论

相关推荐

    asp.net fileupload文件上传

    o asp.net环境一下好的文件上传解决方案 有client上控制说明,也有sever上控制说明

    FileUpload+DWR 多文件上传实例

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

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

    C#Fileupload上传控件上传任意大小的文件,内含清晰的解说和配置说明,不错的代码,供大家学习

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

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

    在asp.net中,怎么样用FileUpload上传文件?

    本文通过举例来说明FileUpload控件的用法, 文件的上传在项目开发中经常会使用到,所以,了解文件的上传,还是对你有帮助的!

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

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

    基于commons-fileupload组件的上传下载

    文章为本人所写,向初学者展示了如何进行基于commons-fileupload组件的上传下载的详细开发过程。细致的说明相信能给您带来帮助。

    文件上传 组件fileupload

    fileupload,里面有源码,还有相应的说明文档,很不错的资源,欢迎大家下载学习。

    jsp上传和下载commons-fileupload例子及说明(推荐)

    因为jspsmartupload上传大文件的时候,比较慢。所以这里选择了commons-fileupload这个组件。 在网上有很多文章教我们怎样去做,但是往往都是很难做得出来的! 所以我这里给出了一个完整的例子!里面已经有所需要用到...

    jsf2.0 文件上传组件

    由于JSF2.0标准实现没有提供文件上传组件,而实际应用中很多时候需要上传文件,为了方便开发,我做了一个基于JSF2.0的文件上传组件,上传使用的是Apache 的commons-fileupload组件,我已经将commons-fileupload-...

    struts2文件上传原理说明

    struts2文件上传原理分析文档。使用Commons_fileupload的框架实现上传。

    asp.net与fileUpload.swf实现无刷新多图片上传

    该文件是一个asp.net网站,以简单的代码来说明,在asp.net中flash与IHttpHandler接合实现多图片上传。 这个flash只能上传图片。

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

    统一的接口,不同的实现,很方便的实现上传,代码里面有很详细的说明,相关的包没有上传,请自己下载。。我项目开发的时候一直是用的这几个类

    JSP文件上传示例 附上详细的部署说明

    安装部署说明 1、本章无需数据库及表。 2、Chapter21下包含了所有的源代码和可部署文件,其中.war文件为可部署文件,可以直接部署在Tomcat5.5及以上版本下。 3、如果要重新编译程序,请在MyEclipse 6.0中导入项目...

    文件上传两个插件和使用介绍总结

    里面有两个压缩有一个docx文件,一个txt文件,两个压缩包正是现在最流行使用的java文件上传插件commons-fileupload1.2.2和commons-io.1.3.2,和我个人总结的使用方法。相信看完我上传的文件你会懂的使用这两个上传...

    多文件无刷新上传控件

    &lt;br&gt;控件属性说明: &lt;br&gt;ID Width 控件宽度,IE有效 Height 控件高度 AjaxImage 上传时显示的loading图片路径,默认路径为"/images/ajax.gif" IsMuch 是否多文件 true 多文件上传,false 单...

    [上传下载]仿163网盘无刷新文件上传 for Jsp_fileupload_jsp.rar

    源码说明: 全部项目源码都是经过测试校正后百分百成功运行。 SpringBoot 毕业设计,SpringBoot 课程设计,基于SpringBoot+Vue开发的,含有代码注释,新手也可看懂。ssm整合开发,小程序毕业设计、期末大作业、课程...

    ajax实现上传文件时显示进度条的功能

    实现上传文件时显示进度条的功能。当上传文件时,客户端同时显示文件上传的进度,从而及时了解文件传送情况。 源码结构说明 1.FileUpload文件夹下为源文件 2.FileUpload.war为部署文件 已经试过运行正常

    java文件上传jar包+操作说明文档

    含有commons-fileupload-1.2.1-bin.zip二进制,commons-io-1.4-bin.zip二进制,还有一个pdf操作文档

    研究论文-Struts2架构中的Commons-fileupload组件应用技术.pdf

    基于HTTP传输协议的Web网页中,采用嵌入Commonsfileupload组件的Struts2框架,实现了文件的上传与下载.利用OGNL表达式提取Session持久层中的文件名,并利用此文件名实现下载文件的动态更名.灵活利用struts2.0自身...

Global site tag (gtag.js) - Google Analytics