最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

JSP 文件上传下载

来源:动视网 责编:小OO 时间:2025-10-02 08:11:30
文档

JSP 文件上传下载

MyEclipse6实战开发讲解视频入门10JSP文件上传下载2007-12-2本视频讲解了如何使用最新版本开源的ApacheCommonsFileUpload来上传文件以及如何编写文件下载代码.视频部分代码屏幕出现闪烁,错位,不便之处请参考本文中的源码和文档中绿色部分的注释://Setfactoryconstraintsfactory.setSizeThreshold(yourMaxMemorySize);//设置最多只允许在内存中存储的数据,单位:字节factory.setReposito
推荐度:
导读MyEclipse6实战开发讲解视频入门10JSP文件上传下载2007-12-2本视频讲解了如何使用最新版本开源的ApacheCommonsFileUpload来上传文件以及如何编写文件下载代码.视频部分代码屏幕出现闪烁,错位,不便之处请参考本文中的源码和文档中绿色部分的注释://Setfactoryconstraintsfactory.setSizeThreshold(yourMaxMemorySize);//设置最多只允许在内存中存储的数据,单位:字节factory.setReposito
MyEclipse 6 实战开发讲解视频入门 10 JSP 文件上传下载

2007-12-2

本视频讲解了如何使用最新版本开源的Apache Commons FileUpload 来上传文件以及如何编写文件下载代码. 

视频部分代码屏幕出现闪烁, 错位, 不便之处请参考本文中的源码和文档中绿色部分的注释:

// Set factory constraints

factory.setSizeThreshold(yourMaxMemorySize); // 设置最多只允许在内存中存储的数据,单位:字节

factory.setRepository(yourTempDirectory); // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录(默认可以不用设置)

// Create a new file upload handler

ServletFileUpload upload = new ServletFileUpload(factory);

// Set overall request size constraint

// 设置允许用户上传文件大小,单位:字节

upload.setSizeMax(yourMaxRequestSize);

友情提示: 下载微软网盘文件时关闭下载工具,  否则你将得到错误的文件, 双击 EXE 会出来 DOS 窗口. 正确操作是点击文件名后能看到显示下载链接和文件大小等信息. 

代码: http://cid-519b3f7aa2172030.skydrive.live.com/self.aspx/Public/MyEclipse6Videos/10_JSPFileUploadDownload.zip  132 KB 

视频:  http://cid-519b3f7aa2172030.skydrive.live.com/self.aspx/Public/MyEclipse6Videos/myeclipse6_10.exe 16分31秒 6.0 MB 

内容包括: 

1. Apache Commons FileUpload 项目介绍 

2. 下载并增加必要的类库 

3. 编写文件上传表单 HTML 

4. 编写文件上传处理 JSP 

5. 编写文件下载JSP 

6. 发布并测试 

视频截图: 

代码: 

upload.htm

  

    

      

      

    

    

      

      

    

 

    

附件:

      

    

  

Login:
Password:

upload.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>

<%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>

<%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%> 

<%!/**

     * 得到文件的短路径, 不包括目录.

     * @date 2005-10-18

     *

     * @param fileName

     *            需要处理的文件的名字.

     * @return the short version of the file's name.

     */

    public static String getShortFileName(String fileName) {

        if (fileName != null) {

            String oldFileName = new String(fileName); 

            fileName = fileName.replace('\\\\', '/'); 

            // Handle dir

            if (fileName.endsWith("/")) {

                int idx = fileName.indexOf('/');

                if (idx == -1 || idx == fileName.length() - 1) {

                    return oldFileName;

                } else {

                    return oldFileName

                            .substring(idx + 1, fileName.length() - 1);

                } 

            }

            if (fileName.lastIndexOf("/") > 0) {

                fileName = fileName.substring(fileName.lastIndexOf("/") + 1,

                        fileName.length());

            } 

            return fileName;

        }

        return "";

    }%>

<%

    // Check that we have a file upload request

    boolean isMultipart = ServletFileUpload.isMultipartContent(request); 

    if (isMultipart) {

        // Create a factory for disk-based file items

        org.apache.commons.fileupload.FileItemFactory factory = new DiskFileItemFactory(); 

        // Create a new file upload handler

        ServletFileUpload upload = new ServletFileUpload(factory); 

        // Parse the request

        List /* FileItem */items = upload.parseRequest(request); 

        // Process the uploaded items

        Iterator iter = items.iterator();

        while (iter.hasNext()) {

            org.apache.commons.fileupload.FileItem item = (org.apache.commons.fileupload.FileItem) iter

                    .next(); 

            if (item.isFormField()) {

                String name = item.getFieldName();

                String value = item.getString("GBK");

                out.println(name + "=" + value);

            } else {

                String fieldName = item.getFieldName();//file

                String fileName = item.getName();

                String contentType = item.getContentType();

                boolean isInMemory = item.isInMemory();

                long sizeInBytes = item.getSize(); 

                out.println("上传的文件名是:" + fileName); 

                if (fileName == null || fileName.length() == 0) {

                    out.println("请选择一个文件来上传");

                } else { 

                    java.io.FileOutputStream fout = new java.io.FileOutputStream(

                            application.getRealPath("upload/"

                                    + getShortFileName(fileName)));

                    fout.write(item.get());

                    fout.close();

                }

            }

        }

    } else {

        out.println("请用文件上传表单来访问这个页面");

    }

%>

相关资料: 

下载地址 

http://commons.apache.org/fileupload/  

http://commons.apache.org/io/ 

用法文档: 

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

Using FileUpload

FileUpload can be used in a number of different ways, depending upon the requirements of your application. In the simplest case, you will call a single method to parse the servlet request, and then process the list of items as they apply to your application. At the other end of the scale, you might decide to customize FileUpload to take full control of the way in which individual items are stored; for example, you might decide to stream the content into a database. 

Here, we will describe the basic principles of FileUpload, and illustrate some of the simpler - and most common - usage patterns. Customization of FileUpload is described elsewhere. 

FileUpload depends on Commons IO, so make sure you have the version mentioned on the dependencies page in your classpath before continuing. 

How it works

A file upload request comprises an ordered list of items that are encoded according to RFC 1867, "Form-based File Upload in HTML". FileUpload can parse such a request and provide your application with a list of the individual uploaded items. Each such item implements the FileItem interface, regardless of its underlying implementation. 

This page describes the traditional API of the commons fileupload library. The traditional API is a convenient approach. However, for ultimate performance, you might prefer the faster Streaming API. 

Each file item has a number of properties that might be of interest for your application. For example, every item has a name and a content type, and can provide an InputStream to access its data. On the other hand, you may need to process items differently, depending upon whether the item is a regular form field - that is, the data came from an ordinary text box or similar HTML field - or an uploaded file. The FileItem interface provides the methods to make such a determination, and to access the data in the most appropriate manner. 

FileUpload creates new file items using a FileItemFactory. This is what gives FileUpload most of its flexibility. The factory has ultimate control over how each item is created. The factory implementation that currently ships with FileUpload stores the item's data in memory or on disk, depending on the size of the item (i.e. bytes of data). However, this behavior can be customized to suit your application. 

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 request

boolean 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 items

FileItemFactory factory = new DiskFileItemFactory();

// Create a new file upload handler

ServletFileUpload upload = new ServletFileUpload(factory);

// Parse the request

List /* 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 items

DiskFileItemFactory factory = new DiskFileItemFactory();

// Set factory constraints

factory.setSizeThreshold(yourMaxMemorySize); // 设置最多只允许在内存中存储的数据,单位:字节

factory.setRepository(yourTempDirectory); // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录(默认可以不用设置)

// Create a new file upload handler

ServletFileUpload upload = new ServletFileUpload(factory);

// Set overall request size constraint

// 设置允许用户上传文件大小,单位:字节

upload.setSizeMax(yourMaxRequestSize);

// Parse the request

List /* 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 items

DiskFileItemFactory factory = new DiskFileItemFactory(

        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 items

Iterator iter = items.iterator();

while (iter.hasNext()) {

    FileItem item = (FileItem) 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 field

if (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 upload

if (!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 upload

if (writeToFile) {

    File uploadedFile = new File(...);

    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 memory

byte[] 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 an instance of org.apache.commons.io.FileCleaningTracker, which starts a reaper thread. 

In what follows, we assume that you are writing a web application. In a web application, resource cleanup is controlled by an instance of javax.servlet.ServletContextListener. In other environments, similar ideas must be applied. 

The FileCleanerCleanup

Your web application should use an instance of org.apache.commons.fileupload.FileCleanerCleanup. That's very easy, you've simply got to add it to your web.xml: 

  ...

      org.apache.commons.fileupload.servlet.FileCleanerCleanup

  ...

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

        return new DiskFileItemFactory(fileCleaningTracker,

                                       DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD,

                                       repository);

    }

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 listener

ProgressListener progressListener = new ProgressListener(){

   public void 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 listener

ProgressListener progressListener = new ProgressListener(){

   private long megaBytes = -1;

   public void 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.");

       }

   }

};

What's next

Hopefully this page has provided you with a good idea of how to use FileUpload in your own applications. For more detail on the methods introduced here, as well as other available methods, you should refer to the JavaDocs. 

The usage described here should satisfy a large majority of file upload needs. However, should you have more complex requirements, FileUpload should still be able to help you, with it's flexible customization capabilities. 

RFC1867协议介绍 

RFC1867协议主要是在HTTP协议的基础上为INPUT标签增加了file属性,同时限定了Form的method必须为POST,ENCTYPE必须为multipart/form-data。当然还增加了一些与此相关属性,但都不是很重要,我们在此不作讨论。

在一般的基于Web的程序中,我们往往使用标签,该标签在被浏览器解析后会产生一个文本框和一个浏览按钮,单击浏览按钮会出现系统的文件选择框。

2.       执行上传及标签的一些特性

在上图选择相应的文件,按Upload按钮即可把选择的文件上传到服务器(服务器端可用JspSmartUpload等组件接受文件)。归根结底上传的所有操作都是由浏览器作的,用户所做的只是简单地选择了一下文件而已,接下来的问题是,如何能把一个目录中所有的文件实现一次性上传?

(1)        因为目录下的文件数量是不定的,因此我们基本不可能通过增加多个标签的方式来解决问题。

(2)        如果在Jsp中我们可以考虑以下方式来解决:通过Jsp动态创建标签,并使所创建的标签不可见。把每个标签的Value属性设置为每个文件的路径。在按Upload时再实行一次性上传。在我们试验了之后就会发现,对的Value属性赋值是徒劳的行为,因为RFC1867协议并没有要求浏览器的实现者一定实现Value属性,而IE恰好忽略了Value属性。

即以下代码将是徒劳的(IE中)

 

         //对Value赋值

         Form1.file1.value=”c:\\\\aa.txt”; 

         //执行后,IE将忽略此赋值

<.script>

上述两种方式均无法完成我们需要的功能,接下来我们只能剖析IE是如何完成上传功能,把具体的实现方法用ActiveX或(Applet)来完成。

3.       HTTP协议的简单介绍

一般说来我们认为HTTP协议是构建在TCP/IP之上的协议,其实HTTP协议本身无此,但因现实中多数情况均是如此,我们就姑且如此认为。HTTP数据总体说来分三大部分:

(1)        请求行,如下格式

(Request) POST SP URL SP HTTP/1.1 \\r\\n 

请求方法+空格+请求URL+空格+HTTP协议版本+回车换行

如:POST http://localhost:8080/test/test.jsp HTTP1.1\\r\\n 

(Response)HTTP/1.1 SP 200 SP OK \\r\\n 

HTTP协议应答版本+空格+状态码+状态描述+回车换行

如:HTTP/1.1 200 OK \\r\\n 

请求行主要是描述请求的URL,HTTP协议版本,应答状态等信息。

(2)        请求头

在HttpServletRequest接口里已经封装了对HTTP头操作的方法。如Content-type,Content-length,User-Agent,Host等都是HTTP头。HTTP头主要描述了HTTP所传输数据的一些信息,如主机,数据内容类型,数据长度,代理类型等。

如:

User-Agent: myselfHttp/1.1\\r\\n 

Accept: www/source; text/html; image/gif; */*\\r\\n 

HTTP头+:+空格+头信息+回车换行

(3)        HTTP实体

HTTP实体存放着,HTTP请求的内容,如参数信息,文本框的内容,隐含控件的值,ListBox的值等。如果在页面上存在: 

 

 

HTTP实体会出现以下形式:(POST提交) 

userName=zhangsan&password=123 

GET提交的时候需要解析HTTP请求行中的URL,在此不多作讨论。

4.       RFC1867协议的数据格式

(1)      RFC1867对HTTP头的变更

RFC1867对HTTP头作了适当地变更,但变更很小。首先content-type头由以前的:

content-type: application/x-www-form-urlencoded

变为

content-type: multipart/form-data; +空格+ 

boundary=---------------------------7d52b133509e2

即增加了boundary,所谓的boundary其实就是分割线,下文将看到,RFC1867利用boundary分割HTTP实体数据。boundary中数字字符区是随机生成的。

(2)      对HTTP实体的变更

因为RFC1867增加了文件上传得功能,而上传文件内容自然也会被加入到HTTP的实体中。现在因为既有HTTP一般的参数实体,又有上传文件的实体,所以用boundary把每种实体进行了分割,HTTP的实体看起来将是下面的样子: 

-----------------------------7d52b133509e2

Content-Disposition: form-data; name="file1"; filename="c:\\aa.txt"

Content-Type: text/plain

文件内容在此处

-----------------------------7d52b133509e2

Content-Disposition: form-data; name="userName"

zhangsan

-----------------------------7d52b133509e2

Content-Disposition: form-data; name="password"

123

-----------------------------7d52b133509e2—

{关于实体的其他说明:

Content-type: multipart/form-data, boundary=AaB03x

(\\r\\n)

--AaB03x                                                                             //boundary

content-disposition: form-data; name="user"                  //form 表单变量名

(\\r\\n)

Wilson Peng                                                                      //form 表单变量数据

--AaB03x     

content-disposition: form-data; name="myfile"               //form 表单变量名

Content-type: multipart/mixed, boundary=BbC04y           //新的描述和新的描述和boundary

(\\r\\n)

--BbC04y 

图片名字

Content-type: image/gif                                                           //图片描述

Content-Transfer-Encoding: binary                                        //编码方式

    (\\r\\n)

图片内容略...           

--BbC04y-- 

--AaB03x--

}

很明显,增加了文件上传后,HTTP实体变得稍微复杂了,首先是通过boundary把实体分开,以便于读取,然后对FileUpload的格式也作了。

(3)      RFC1867协议的数据格式 

根据RFC1867协议,在HTTP实体中必须对每个上传得文件有说明头,如:

Content-Disposition: form-data; name="file1";

filename="c:\\aa.txt"

Content-Disposition:指明内容类型是form-data

name="file1":指明页面上标签的名字是file1

filename="c:\\aa.txt":指明上传文件在客户端上的全路径

空行:文件头说明完毕后,要加一空行,以表示后面的数据是文件的内容

文件内容:再接下来就是文件的内容

从这个角度说,完全可以利用HTTP协议+RFC1867协议开发基于文档管理应用程序。

5.       协议的实现(客户端)

协议的好处就是,只要你提供的数据符合协议的要求,Server端就可以正确解析你的请求。而不论数据是由IE产生的,或有你自己的Application产生的。通过上面的分析,我们已经基本清楚了RFC1867协议的要求,只要我们打开指定的端口,把数据按照协议的要求写进去就会模拟出IE上传的功能。用程序实现是非常Easy的事。附件将给出Java实现版本,程序只是简单地实现了上传,根据我们前面的分析实现文件上传,参数传递这种稍麻烦的形式也是比较简单的。另外,该程序并没有实现返回数据的解析,同样根据我们前面的分析,按照HTTP协议去解析返回的数据也不是难事。总之,希望本程序能起到抛砖引玉的作用,

6.代码实现

转]通过 http 协议上传文件

2008-04-30 23:55

1、概述

在最初的 http 协议中,没有上传文件方面的功能。 rfc1867 ( http://www.ietf.org/rfc/rfc1867.txt ) 为 http 协议添加了这个功能。客户端的浏览器,如 Microsoft IE, Mozila, Opera 等,按照此规范将用户指定的文件发送到服务器。服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件。

Microsoft IE, Mozila, Opera 已经支持此协议,在网页中使用一个特殊的 form 就可以发送文件。

绝大部分 http server ,包括 tomcat ,已经支持此协议,可接受发送来的文件。

各种网页程序,如 php, asp, jsp 中,对于上传文件已经做了很好的封装。

2、上传文件的实例:用 servelet 实现(http server 为 tomcat 4.1.24)

1. 在一个 html 网页中,写一个如下的form :

    load multi files :

    

   

   

   

    text field :

    

2. 服务端 servelet 的编写

现在第三方的 http upload file 工具库很多。Jarkata 项目本身就提供了fileupload 包http://jakarta.apache.org/commons/fileupload/ 。文件上传、表单项处理、效率问题基本上都考虑到了。在 struts 中就使用了这个包,不过是用 struts 的方式另行封装了一次。这里我们直接使用 fileupload 包。至于struts 中的用法,请参阅 struts 相关文档。

这个处理文件上传的 servelet 主要代码如下:

public void doPost( HttpServletRequest request, HttpServletResponse response ) {

    DiskFileUpload diskFileUpload = new DiskFileUpload();

    // 允许文件最大长度

    diskFileUpload.setSizeMax( 100*1024*1024 );

    // 设置内存缓冲大小

    diskFileUpload.setSizeThreshold( 4096 );

    // 设置临时目录

    diskFileUpload.setRepositoryPath( "c:/tmp" );

    List fileItems = diskFileUpload.parseRequest( request );

    Iterator iter = fileItems.iterator();

    for( ; iter.hasNext(); ) {

        FileItem fileItem = (FileItem) iter.next();

        if( fileItem.isFormField() ) {

            // 当前是一个表单项

            out.println( "form field : " + fileItem.getFieldName() + ", " + fileItem.getString() );

        } else {

            // 当前是一个上传的文件

            String fileName = fileItem.getName();

            fileItem.write( new File("c:/uploads/"+fileName) );

        }

    }

}

为简略起见,异常处理,文件重命名等细节没有写出。

3、 客户端发送内容构造

假设接受文件的网页程序位于 http://192.168.29.65/upload_file/UploadFile.

假设我们要发送一个二进制文件、一个文本框表单项、一个密码框表单项。文件名为 E:\\s ,其内容如下:(其中的XXX代表二进制数据,如 01 02 03)

a

bb

XXX

ccc

客户端应该向 192.168.29.65 发送如下内容:

POST /upload_file/UploadFile HTTP/1.1

Accept: text/plain, */*

Accept-Language: zh-cn

Host: 192.168.29.65:80

Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6

User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)

Content-Length: 424

Connection: Keep-Alive

-----------------------------7d33a816d302b6

Content-Disposition: form-data; name="userfile1"; filename="E:\\s"

Content-Type: application/octet-stream

a

bb

XXX

ccc

-----------------------------7d33a816d302b6

Content-Disposition: form-data; name="text1"

foo

-----------------------------7d33a816d302b6

Content-Disposition: form-data; name="password1"

bar

-----------------------------7d33a816d302b6--

此内容必须一字不差,包括最后的回车。

注意:Content-Length: 424 这里的424是红色内容的总长度(包括最后的回车)

注意这一行:

Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6

根据 rfc1867, multipart/form-data是必须的.

---------------------------7d33a816d302b6 是分隔符,分隔多个文件、表单项。其中33a816d302b6 是即时生成的一个数字,用以确保整个分隔符不会在文件或表单项的内容中出现。前面的 ---------------------------7d 是 IE 特有的标志。 Mozila 为---------------------------71

用手工发送这个例子,在上述的 servlet 中检验通过。

(上面有一个回车)用户可以选择多个文件,填写表单其它项,点击“提交”按钮后就开始上传给 http://192.168.29.65/upload_file/UploadFile

 这是一个 servelet 程序

注意 enctype="multipart/form-data", method=post, type="file" 。根据 rfc1867, 这三个属性是必须的。multipart/form-data 是新增的编码类型,以提高二进制文件的传输效率。具体的解释请参阅 rfc1867

文档

JSP 文件上传下载

MyEclipse6实战开发讲解视频入门10JSP文件上传下载2007-12-2本视频讲解了如何使用最新版本开源的ApacheCommonsFileUpload来上传文件以及如何编写文件下载代码.视频部分代码屏幕出现闪烁,错位,不便之处请参考本文中的源码和文档中绿色部分的注释://Setfactoryconstraintsfactory.setSizeThreshold(yourMaxMemorySize);//设置最多只允许在内存中存储的数据,单位:字节factory.setReposito
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top