使用FileUpload实现Servlet的文件上传

本文详细介绍如何使用Apache Commons FileUpload库实现Java环境下的文件上传功能,包括配置与使用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

FileUpload 是 Apache commons下面的一个子项目,用来实现Java环境下的文件上传功能。

FileUpload链接

FileUpload 是基于Apache的Commons IO的,所以在使用之前需要先在BuildPath种添加Commons IO。

Commons IO链接


1.在项目种添加Commons IO和FileUpload

1.1下载Commons IO的最新版本

链接

1.2下载FileUpLoad的最新版本

链接

注:tar.gz是linux版本的

1.3分别把两个jar文件复制到项目文件夹下

个人喜欢放在WEB-INF>lib下:

分别对两个jar文件执行如下操作:

注意:两个jar文件都要Add to Build Path,另外别忘了在java文件里还要import


2.按照Apache官网给出的指导使用文件上传

官网指导链接

2.0在html文件或者jsp文件里创建一个上传文件的表单

这里我创建的是一个jsp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<%@  page language= "java"  contentType= "text/html; charset=UTF-8"
     pageEncoding= "UTF-8" %>
<!DOCTYPE html PUBLIC  "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd" >
<html>
<head>
<meta http-equiv= "Content-Type"  content= "text/html; charset=UTF-8" >
<title>Insert title here</title>
</head>
<body>
<h1>文件上传</h1>
 
 
<form method= "POST"  enctype= "multipart/form-data"  action= "UpLoadFile"  name= "uploadForm" >
   选择一个文件: <input type= "file"  name= "upfile" ><br/>
   <br/>
   <input type= "submit"  value= "上传" >
</form>
 
 
</body>
</html>

  运行如下:

用到的一些类的说明:

DiskFileItemFactory——工厂类

ServletFileUpload——用于解析resquest,能从resquest中解析出装有FileItem对象的一个List

FileItem——每个FileItem的实例都包含一个文件以及该文件的其他一些属性(文件名、大小等)

注意:以下部分翻译自官网指导。原文链接

2.1使用FileUpload

FileUpload可以通过多种不同的方式使用,具体的使用方式取决于您的应用要求。最简单的方式,您将调用一种方法来解析servlet请求到一个List中。

2.2FileUpLoad是如何运行的

FileUpload可以解析一个请求(request),并向应用程序提供上传的items(上传的文件表单项目)的一个List。每个文件项目(items)都有一些你的应用程序可能感兴趣的属性,例如name、content type,每个items还能提供一个“InputStream”。

FileUpload使用FileItemFactory类来创建新的items,FileUpload附带的FileItemFactory类的实例将项目的数据存储在内存或磁盘上,具体取决于项目的大小(即数据字节数)。但是,可以自定义此行为。

2.3解析请求

在使用上传的items之前,需要解析请求本身,确保请求实际上是一个文件上传请求可用。

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

  

2.4最简单的一种使用情况

  • 只要上传的项目足够小,应保留在内存中。
  • 较大的项目应写入磁盘上的临时文件。
  • 不应该允许非常大的上传请求。
  • 内存中默认保留的内容的最大容量,上传请求的最大允许大小以及临时文件的位置是可以接受的(这一句是Google翻译的)
复制代码
// 创建工厂(这里用的是工厂模式)
DiskFileItemFactory factory = new DiskFileItemFactory();
//获取汽车零件清单与组装说明书(从ServletContext中得到上传来的数据)
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
//工厂把将要组装的汽车的参数录入工厂自己的系统,因为要根据这些参数开设一条生产线(上传来的文件的各种属性)
factory.setRepository(repository);
//此时工厂中已经有了汽车的组装工艺、颜色等属性参数(上传来的文件的大小、文件名等)
//执行下面的这一行代码意味着根据组装工艺等开设了一条组装生产线
ServletFileUpload upload = new ServletFileUpload(factory);
复制代码

 

 这样我门就获得了一个List。

Servlet完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package  com.feipeng8848;
 
import  java.io.File;
import  java.io.FileOutputStream;
import  java.io.IOException;
import  java.io.InputStream;
import  java.io.OutputStream;
import  java.io.PrintWriter;
import  java.util.Iterator;
import  java.util.List;
  
import  javax.servlet.ServletContext;
import  javax.servlet.ServletException;
import  javax.servlet.http.HttpServlet;
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;
  
import  org.apache.commons.fileupload.FileItem;
import  org.apache.commons.fileupload.FileUploadException;
import  org.apache.commons.fileupload.disk.DiskFileItemFactory;
import  org.apache.commons.fileupload.servlet.ServletFileUpload;
 
 
 
 
/**
  * Servlet implementation class UpLoadExcelServlet
  */
 
public  class  UpLoadExcelServlet  extends  HttpServlet {
     private  static  final  long  serialVersionUID = 1L;
        
     /**
      * @see HttpServlet#HttpServlet()
      */
     public  UpLoadExcelServlet() {
         super ();
         // TODO Auto-generated constructor stub
     }
 
     /**
      * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
      */
     protected  void  doGet(HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException {
         response.setContentType( "text/html;charset=UTF-8" );
         PrintWriter out = response.getWriter();
         out.println( "<!DOCTYPE html>\n" );
         out.println( "<head><title>PageTitle</title></head>" );
         out.println( "<body>" );
         out.println( "<p>文件已经上传成功</p>" );
         out.println( "</body>" );
     }
 
     /**
      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
      */
     protected  void  doPost(HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException {
         // TODO Auto-generated method stub
         doGet(request, response);
         System.out.println( "doPost" );
         
         boolean  isMultipart = ServletFileUpload.isMultipartContent(request);
          
         if  (isMultipart) {
             System.out.println( "True" );
             
             // 创建工厂(这里用的是工厂模式)
             DiskFileItemFactory factory =  new  DiskFileItemFactory();
             //获取汽车零件清单与组装说明书(从ServletContext中得到上传来的数据)
             ServletContext servletContext =  this .getServletConfig().getServletContext();
             File repository = (File) servletContext.getAttribute( "javax.servlet.context.tempdir" );
             //工厂把将要组装的汽车的参数录入工厂自己的系统,因为要根据这些参数开设一条生产线(上传来的文件的各种属性)
             factory.setRepository(repository);
             //此时工厂中已经有了汽车的组装工艺、颜色等属性参数(上传来的文件的大小、文件名等)
             //执行下面的这一行代码意味着根据组装工艺等开设了一条组装生产线
             ServletFileUpload upload =  new  ServletFileUpload(factory);
  
             //解析请求
             try  {
                 //把零件送给生产线,出来的就是一辆组装好的汽车(把request转成FileItem的实例)
                 List<FileItem> items = upload.parseRequest(request);
                 Iterator<FileItem> iter = items.iterator();
                 while  (iter.hasNext()) {
                     FileItem item = iter.next();
                     //创建文件输出流
                     File file= new  File( "D:\\b.xlsx" );
                     if (!file.exists())
                     {
                         try  {   
                             file.createNewFile();   
                         catch  (IOException e) {   
                             e.printStackTrace();   
                         }   
                     }
                     FileOutputStream fos= new  FileOutputStream(file);                 
                     //创建输入流
                     InputStream fis=(InputStream) item.getInputStream();
                     //从输入流获取字节数组
                     byte  b[]= new  byte [ 1 ];
                     //读取一个输入流的字节到b[0]中
                     int  read=fis.read(b);
                     while (read!=- 1
                    
                         fos.write(b, 0 , 1 ); 
                         read=fis.read(b); 
                    
                     fis.close();
                     fos.flush();
                     fos.close();
                     //打印List中的内容(每一个FileItem的实例代表一个文件,执行这行代码会打印该文件的一些基本属性,文件名,大小等)
                     System.out.println(item);  
                 }
                 System.out.println( "循环输出完成" );
             catch  (FileUploadException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
         else  {
         System.out.println( "False" );
         }  
     }
}

  

 

  选择一个文件:

输出:

输出的完整内容:

1
2
3
4
doPost
True
name=PRICIPLE_k.png, StoreLocation=C:\Users\k\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\DBControler\upload_cae42561_32ce_45d4_9009_<br>ec94523a4b02_00000000.tmp, size= 24914  bytes, isFormField= false , FieldName=upfile
循环输出完成

 



  1. import java.io.File;   
  2. import java.util.ArrayList;   
  3. import java.util.Iterator;   
  4. import java.util.List;   
  5.   
  6. import javax.servlet.RequestDispatcher;   
  7. import javax.servlet.ServletException;   
  8. import javax.servlet.http.HttpServlet;   
  9. import javax.servlet.http.HttpServletRequest;   
  10. import javax.servlet.http.HttpServletResponse;   
  11.   
  12. import org.apache.commons.fileupload.FileItem;   
  13. import org.apache.commons.fileupload.disk.DiskFileItemFactory;   
  14. import org.apache.commons.fileupload.servlet.ServletFileUpload;   
  15.   
  16. public class UploadFileServlet extends HttpServlet {   
  17.     private static final long serialVersionUID = 56890894234786L;   
  18.      String saveFolder = "falshFolder";   
  19.      String saveTempFolder = "falshTempFolder";   
  20.   
  21.     @SuppressWarnings("unchecked")   
  22.     public void doPost(HttpServletRequest request, HttpServletResponse response)   
  23.             throws ServletException, java.io.IOException {   
  24.          request.setCharacterEncoding("UTF-8");   
  25.   
  26.         // 文件上傳部分   
  27.         boolean isMultipart = ServletFileUpload.isMultipartContent(request);   
  28.            
  29.         if (isMultipart == true) {   
  30.             try {   
  31.                 // 实例化一个硬盘文件工厂,用来配置上传组件ServletFileUpload   
  32.                  DiskFileItemFactory factory = new DiskFileItemFactory();   
  33.                 // 设置上传文件时用于临时存放文件的内存大小,这里是4K.多于的部分将临时存在硬盘   
  34.                  factory.setSizeThreshold(4096);   
  35.                 //设置存放临时文件的目录,web根目录下的ImagesUploadTemp目录   
  36.                  factory.setRepository(new File(request.getRealPath("/")+   
  37.                          saveTempFolder));   
  38.                 // 用配置好的工厂实例化上传组件   
  39.                  ServletFileUpload upload = new ServletFileUpload(factory);   
  40.                    
  41.                 // 得到所有的表单域,它们目前都被当作FileItem   
  42.                  List<FileItem> fileItems = upload.parseRequest(request);   
  43.                  Iterator<FileItem> iter = fileItems.iterator();   
  44.                    
  45.                 // 依次处理每个表单域   
  46.                 while (iter.hasNext()) {   
  47.                      FileItem item = (FileItem) iter.next();   
  48.                        
  49.                     if(item.isFormField()){   
  50.                         // 如果item是正常的表单域   
  51.                          String name = item.getFieldName();   
  52.                          String value = item.getString();   
  53.                          System.out.print("表单域名为:"+name+"表单域值为:"+value);   
  54.                      }   
  55.                     else{   
  56.                         // 如果item是文件上传表单域   
  57.                            
  58.                         // 获得文件名及路径   
  59.                          String fileName = item.getName();   
  60.                         if (fileName != null) {   
  61.                             //获取要上传的文件   
  62.                              File fullFile = new File(item.getName());      
  63.                              String t_ext = fullFile.getName().substring(fullFile.getName().lastIndexOf(".") + 1);   
  64.   
  65.                             // 如果文件存在则上传   
  66.                             if(fullFile.exists()){   
  67.                                 //存放文件的路径   
  68.                                  String filePath = request.getRealPath("/") + saveFolder;   
  69.                                 long now = System.currentTimeMillis();   
  70.                                 // 根据系统时间生成上传后保存的文件名   
  71.                                  String name = String.valueOf(now);   
  72.                                  File fileOnServer = new File(filePath,   
  73.                                          name+"."+t_ext);   
  74.                                  item.write(fileOnServer);   
  75.                                    
  76.                                  System.out.println("文件"+fileOnServer.getName()+"上传成功");   
  77.                                  request.setAttribute("fileName", fullFile.getName());   
  78.                              }   
  79.                          }   
  80.                      }   
  81.                  }                   
  82.              } catch (Exception e) {   
  83.                  e.printStackTrace();   
  84.              }   
  85.          } else {   
  86.              System.out.println("the enctype must be multipart/form-data");   
  87.          }   
  88.            
  89.   
  90.         // 返回原页   
  91.          RequestDispatcher dispatcher = request   
  92.                  .getRequestDispatcher("index.jsp");   
  93.          dispatcher.forward(request, response);   
  94.         return;   
  95.      }   
  96.   
  97.     public void doGet(HttpServletRequest request, HttpServletResponse response)   
  98.             throws ServletException, java.io.IOException {   
  99.          doPost(request, response);   
  100.      }   
  101.   
  102. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值