疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

文件上传(Java)


 

 
[1] 简介
        > 将一个客户端的本地的文件发送到服务器中保存。
        > 上传文件是通过流的形式将文件发送给服务器。
    
    [2] 表单的设置(文件上传一般利用表单)
    
        > 向服务器上传一个文件时,表单要使用post请求。
        > 表单的默认属性enctype="application/x-www-form-urlencoded"
            - 这个属性的意思是请求体中的内容将会使用URL编码
        > 上传文件的表单enctype需要设置为 multipart/form-data
            - multipart/form-data表示的是表单是一个多部件的表单
            - 如果类型设置为它,则我们的每一个表单项都会作为一个单独的部件发送给服务器。
            - 多个部件之间使用类似 -----------------------------7df2d08c0892 分割符来分开
        > 当表单设置为multipart/form-data时,我们request.getParameter()将失效,我们不能再通过该方法获取请求参数。
 
1 <form action="${pageContext.request.contextPath }/FileUploadServlet" method="post" enctype="multipart/form-data">
2         用户:<input type="text" name="name">
3         <input type="file" name="photo"><br>
4         <input type="submit" value="提交">
5    </form>
    [3] FileUpload
        > 我们一般情况下使用commons-fileupload-1.3.1.jar这个工具来解析多部件请求。
        > fileupload 依赖 commons-io 所以我们要是Filtupload需要同时导入io包。
        > 核心类:
            DiskFileItemFactory
                - 工厂类,用于构建一个解析器实例。
                
            ServletFileUpload
                - 解析器类,通过该类实例来解析request中的请求信息。
                
            FileItem
                - 工具会将我们请求中每一个部件,都封装为一个FileItem对象,处理文件上传时,只需要调用该对象的方法
                -    方法:
                    boolean    isFormField()  --> 当前表单项是否是一个普通表单项,true是普通表单项, false是文件表单项
                    String    getContentType() --> 返回的是文件的类型,是MIME值
                    String    getFieldName()   --> 获取表单项的name属性值
                    String    getName()         --> 获取上传的文件的名字
                    long getSize()          --> 获取文件的大小
                    String    getString(String encoding) --> 获取表单项的value属性值,需要接受一个编码作为参数。
                    void    write(File file)    --> 将表单项中的内容写入到磁盘中
                
        > 使用步骤:
            1.获取工厂类实例[DiskFileItemFactory]
            2.获取解析器类实例[ServletFileUpload]
            3.解析request获取FileItem[parseRequest()]       
 
      
复制代码
 1 @WebServlet("/FileUploadServlet")
 2 public class FileUploadServlet extends HttpServlet {
 3     private static final long serialVersionUID = 1L;
 4  
 5     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 6 
 7         //创建工厂类
 8         DiskFileItemFactory factory=new DiskFileItemFactory();
 9         //创建FileUploadServlet对象,通过这个对象完成上传功能
10         ServletFileUpload fileUpload=new ServletFileUpload(factory);
11         //用这个fileUpload对象解析request请求
12         try {
13             List<FileItem> fileList = fileUpload.parseRequest(request);
14             for(FileItem item:fileList){
15                 if (item.isFormField()) {
16                     //代表普通表单项
17                     String name = item.getFieldName();
18                     String value = item.getString("UTF8");
19                     System.out.println(name+":"+value);
20                 }else {
21                     //代表上传的文件
22                     long size = item.getSize();
23                     String contentType = item.getContentType();
24                     String name = item.getName();
25                     String fieldName = item.getFieldName();
26                                     System.out.println(size+":"+contentType+":"+name+":"+fieldName);
27                     String uuid = UUID.randomUUID().toString();//名字重复,后一章会覆盖前一章
28                     uuid.replace("-", "");
29                     item.write(new File("C:\Users\kanglu\Desktop\"+uuid+"_"+name));
30                 }//MIME 
31             }
32         }catch (Exception e) {
33             // TODO Auto-generated catch block
34             e.printStackTrace();
35         }
36     }
37 }
复制代码
    [4] 细节
        第一个问题
        > 部分浏览器会将文件的完整路径作为文件名发送。
            C:UserslilichaoDesktopday20图片蒙娜丽莎.jpg
        > 像这类文件名我们需要截取一下字符串,只获取名字这部分,而不需要获取路径部分的信息。
            通过如下代码对文件名进行截取字符串的操作:
                if(name.contains("\")){
                    //如果包含则截取字符串
                    name = name.substring(name.lastIndexOf("\")+1);
                }
              
        第二个问题
        > 上传的文件有可能出现重名,后上传的文件会将先上传的文件覆盖。
        > 解决:给文件名加一个唯一的前缀。
                唯一标识_fennu.jpg
                UUID_fennu.jpg   
 
1  //添加唯一前缀
2  String uuid = UUID.randomUUID().toString();//名字重复,后一章会覆盖前一章
3                  uuid.replace("-", "");
 
 
        第三个问题
        > 有些情况需要限制上传文件的大小。
            - 设置单个文件大小为50KB:
                fileUpload.setFileSizeMax(1024*50);
            - 设置完单个文件大小限制以后,一旦上传的文件超过限制,则会抛出如下异常:
                FileSizeLimitExceededException
                所有可以对该异常进行捕获,当出现该异常时则设置一个错误消息。
            
            - 设置多个文件的总大小为150KB
                fileUpload.setSizeMax(1024*150);
            - 当多个文件的大小超出范围时,会抛出如下异常
                SizeLimitExceededException
 
 
复制代码
 1 //单个文件
 2 fileUpload.setFileSizeMax(1024*50);
 3 try{
 4         ......
 5 }catch (FileSizeLimitExceededException e) {
 6     System.out.println("文件大小超出限制");
 7 }
 8 
 9 //多个文件
10 设置插入多个文件
11 <input type="file" name="photo"><br>
12 <input type="file" name="photo"><br>
13 限制大小处理
14 fileUpload.setSizeMax(1024*150);
15 try{
16         ......
17 }catch (SizeLimitExceededException e) {
18     System.out.println("整体文件大小超出限制");
19 }
复制代码
        第四个问题
            > 当用户上传一个空的文件,依然会将文件保存到硬盘上。
            > 在保存文件应该先对文件的大小进行判断,如果size为0,则不处理。
 
复制代码
1 long size = item.getSize();
2 if(size==0){
3     System.out.println("文件大小为空");
4     continue;
5 }//若是多个文件,空文件可能位于首位,所以用continue;
6 //若是单个文件,可用break;
7 //此处针对上面所写代码,其位于for循环中
复制代码
 
 
  [5]上传服务器
 
    上面代码中文件直接传到自己的电脑上,用户不能通过浏览器进行网络访问。
 
    若要能通过浏览器访问,可上传到tomcat服务器位于eclipse的镜像中。(本人使用的是eclipse进行编码)
 
复制代码
 1  将文件上传到服务器上:
 2   1、将links和tc-servlet包复制到eclipse文件目录下;
 3  
 4   2、    //将文件存在tomcat服务器镜像上,获取镜像目录
 5       ServletContext servletContext=request.getServletContext();
 6       String realPath = servletContext.getRealPath("/upload");//要存储的具体位置
 7       File file = new File(realPath);
 8       if(!file.exists()){
 9           file.mkdirs();//文件不存在,创建文件(目录)
10          //file.isDirectory()表明上传的文件是个目录
11      }
复制代码
 
 
   通过realPath获取文件所在位置,在浏览器上输入(如图片地址),即可获取
 
1  localhost:9999/web-upload/upload/168ea717-401b-485c-9d1f-c62cfa50d361_fennu.jpg
2  //在浏览器地址栏输入如上地址内容即可查看刚刚上传的文件(以图片为例),
3  //localhost:9999为tomcat端口号,web-upload为所写项目名,
4  //upload为文件所在位置,
5  //168ea717-401b-485c-9d1f-c62cfa50d361_fennu.jpg为图片名
6 6//_前内容为随机生成的唯一标识符
 
 完整代码,包含上传服务器:
 
package com.neuedu.servlet;
 
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
 
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
 
@WebServlet("/FileUploadServlet")
public class FileUploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
  
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
        //创建工厂类
        DiskFileItemFactory factory=new DiskFileItemFactory();
        //创建FileUploadServlet对象,通过这个对象完成上传功能
        ServletFileUpload fileUpload=new ServletFileUpload(factory);
         
        fileUpload.setFileSizeMax(1024*50);
         
        //将文件上传到服务器,是能在互联网上访问
        ServletContext servletContext=request.getServletContext();
        String realPath = servletContext.getRealPath("/upload");
        File file = new File(realPath);
        if(!file.exists()){
            file.mkdirs();//文件不存在,创建文件(目录)
            //file.isDirectory()表明上传的文件是个目录
        }
         
 
        //用这个fileUpload对象解析request请求
        try {
            List<FileItem> fileList = fileUpload.parseRequest(request);
            for(FileItem item:fileList){
                if (item.isFormField()) {
                    //代表普通表单项
                    String name = item.getFieldName();
                    String value = item.getString("UTF8");
                    System.out.println(name+":"+value);
                }else {
                    //代表上传的文件
                    fileUpload.setFileSizeMax(1024*50);
                    long size = item.getSize();
                    String contentType = item.getContentType();
                    String name = item.getName();
                    String fieldName = item.getFieldName();
                    if(size==0){
                        System.out.println("文件大小为空");
                        continue;
                    }
                    System.out.println(size+":"+contentType+":"+name+":"+fieldName);
                    String uuid = UUID.randomUUID().toString();//名字重复,后一章会覆盖前一章
                    uuid.replace("-", "");
                    try {
                        item.write(new File(realPath+"\"+uuid+"_"+name));
                    } catch (Exception e) {
                        // TODO: handle exception
                    }
                }//MIME
            }
        }catch (FileSizeLimitExceededException e) {
            System.out.println("文件大小超出限制");
        }
        catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
}