javaWEB 之文件的上传

放肆的年华 提交于 2019-12-01 09:56:30

1.1 文件上传三要素

提供form表单,method必须是post

form表单的enctype必须是multipart/form-data

提供 input type=file” 类型输入

1.2 实现文件上传

1.2.1 项目准备

​ 导入: commons-fileupload.jar

​ commons-io.jar

1.2.2 编写上传页面

<%@ page language="java" pageEncoding="UTF-8"%>

<!DOCTYPE HTML>

<html>

  <head>

    <title>文件上传</title>

  </head>

  <body>

    <form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post">

        上传用户:<input type="text" name="username"><br/>

        上传文件1<input type="file" name="file1"><br/>

        上传文件2<input type="file" name="file2"><br/>

        <input type="submit" value="提交">

    </form>

  </body>

</html>

1.2.3 编写处理代码

package me.gacl.web.controller;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.List;

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.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadHandleServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

                //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全

                String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");

                File file = new File(savePath);

                //判断上传文件的保存目录是否存在

                if (!file.exists() && !file.isDirectory()) {

                    System.out.println(savePath+"目录不存在,需要创建");

                    //创建目录

                    file.mkdir();

                }

                //消息提示

                String message = "";

                try{

                    //使用Apache文件上传组件处理文件上传步骤:

                    //1、创建一个DiskFileItemFactory工厂

                    DiskFileItemFactory factory = new DiskFileItemFactory();

                    //2、创建一个文件上传解析器

                    ServletFileUpload upload = new ServletFileUpload(factory);

                     //解决上传文件名的中文乱码

                    upload.setHeaderEncoding("UTF-8");

                    //3、判断提交上来的数据是否是上传表单的数据

                    if(!ServletFileUpload.isMultipartContent(request)){

                        //按照传统方式获取数据

                        return;

                    }

                    //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项

                    List<FileItem> list = upload.parseRequest(request);

                    for(FileItem item : list){

                        //如果fileitem中封装的是普通输入项的数据

                        if(item.isFormField()){

                            String name = item.getFieldName();

                            //解决普通输入项的数据的中文乱码问题

                            String value = item.getString("UTF-8");

                            //value = new String(value.getBytes("iso8859-1"),"UTF-8");

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

                        }else{//如果fileitem中封装的是上传文件

                            //得到上传的文件名称,

                            String filename = item.getName();

                            System.out.println(filename);

                            if(filename==null || filename.trim().equals("")){

                                continue;

                            }

                            //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt

                            //处理获取到的上传文件的文件名的路径部分,只保留文件名部分

                            filename = filename.substring(filename.lastIndexOf("\\")+1);

                            //获取item中的上传文件的输入流

                            InputStream in = item.getInputStream();

                            //创建一个文件输出流

                            FileOutputStream out = new FileOutputStream(savePath + "\\" + filename);

                            //创建一个缓冲区

                            byte buffer[] = new byte[1024];

                            //判断输入流中的数据是否已经读完的标识

                            int len = 0;

                            //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据

                            while((len=in.read(buffer))>0){

                                //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中

                                out.write(buffer, 0, len);

                            }

                            //关闭输入流

                            in.close();

                            //关闭输出流

                            out.close();

                            //删除处理文件上传时生成的临时文件

                            item.delete();

                            message = "文件上传成功!";

                        }

                    }

                }catch (Exception e) {

                    message= "文件上传失败!";

                    e.printStackTrace();   

                }

                request.setAttribute("message",message);

                request.getRequestDispatcher("/message.jsp").forward(request, response);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

}

1.2.4 配置

<servlet>

    <servlet-name>UploadHandleServlet</servlet-name>

    <servlet-class>com.qf.web.UploadHandleServlet</servlet-class>

</servlet>

<servlet-mapping>

    <servlet-name>UploadHandleServlet</servlet-name>

    <url-pattern>/servlet/UploadHandleServlet</url-pattern>

</servlet-mapping>

1.3 文件上传细节注意

上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的

1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。

3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。

4、要限制上传文件的最大值。

5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

最终处理代码改进为:

public class UploadHandleServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全

String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");

//上传时生成的临时文件保存目录

String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");

File tmpFile = new File(tempPath);

if (!tmpFile.exists()) {

//创建临时目录

tmpFile.mkdir();

}

//消息提示

String message = “”;

try{

//使用Apache文件上传组件处理文件上传步骤:

//1、创建一个DiskFileItemFactory工厂

DiskFileItemFactory factory = new DiskFileItemFactory();

//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。

factory.setSizeThreshold(1024100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB

//设置上传时生成的临时文件的保存目录

factory.setRepository(tmpFile);

//2、创建一个文件上传解析器

ServletFileUpload upload = new ServletFileUpload(factory);

//解决上传文件名的中文乱码

upload.setHeaderEncoding(UTF-8);

//3、判断提交上来的数据是否是上传表单的数据

if(!ServletFileUpload.isMultipartContent(request)){

//按照传统方式获取数据

return;

}

//设置上传单个文件的大小的最大值,目前是设置为10241024字节,也就是1MB

upload.setFileSizeMax(10241024);

//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB

upload.setSizeMax(10241024*10);

//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项

List list = upload.parseRequest(request);

for(FileItem item : list){

//如果fileitem中封装的是普通输入项的数据

if(item.isFormField()){

String name = item.getFieldName();

//解决普通输入项的数据的中文乱码问题

String value = item.getString(UTF-8);

//value = new String(value.getBytes(iso8859-1),UTF-8);

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

}else{//如果fileitem中封装的是上传文件

//得到上传的文件名称,

String filename = item.getName();

System.out.println(filename);

if(filename==null || filename.trim().equals("")){

continue;

}

//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt

//处理获取到的上传文件的文件名的路径部分,只保留文件名部分

filename = filename.substring(filename.lastIndexOf("\")+1);

//得到上传文件的扩展名

String fileExtName = filename.substring(filename.lastIndexOf(".")+1);

//如果需要限制上传的文件类型,那么可以通过MT4下载教程文件的扩展名来判断上传的文件类型是否合法

System.out.println(“上传的文件的扩展名是:”+fileExtName);

//获取item中的上传文件的输入流

InputStream in = item.getInputStream();

//得到文件保存的名称

String saveFilename = FileUploadUtils.makeFileName(filename);

//得到文件的保存目录

String realSavePath = FileUploadUtils.makePath(saveFilename, savePath);

//创建一个文件输出流

FileOutputStream out = new FileOutputStream(realSavePath + \+ saveFilename);

//创建一个缓冲区

byte buffer[] = new byte[1024];

//判断输入流中的数据是否已经读完的标识

int len = 0;

//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据

while((len=in.read(buffer))>0){

//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + \+ filename)当中

out.write(buffer, 0, len);

}

//关闭输入流

in.close();

//关闭输出流

out.close();

//删除处理文件上传时生成的临时文件

//item.delete();

message = “文件上传成功!”;

}

}

}catch (FileUploadBase.FileSizeLimitExceededException e) {

e.printStackTrace();

request.setAttribute(message, “单个文件超出最大值!!!”);

request.getRequestDispatcher("/message.jsp").forward(request, response);

return;

}catch (FileUploadBase.SizeLimitExceededException e) {

e.printStackTrace();

request.setAttribute(message, “上传文件的总的大小超出限制的最大值!!!”);

request.getRequestDispatcher("/message.jsp").forward(request, response);

return;

}catch (Exception e) {

message= “文件上传失败!”;

e.printStackTrace();

}

request.setAttribute(message,message);

request.getRequestDispatcher("/message.jsp").forward(request, response);

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

        throws ServletException, IOException {

    doGet(request, response);

}

}

//文件上传工具类

public class FileUploadUtils {

/**

* @Method: makeFileName

* @Description: 生成上传文件的文件名,文件名以:uuid+""+文件的原始名称

* @Anthor:孤傲苍狼

* @param filename 文件的原始名称

* @return uuid+""+文件的原始名称

*/

private static String makeFileName(String filename){ //2.jpg

//为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名

return UUID.randomUUID().toString() + _+ filename;

}

/**

 * 为防止一个目录下面出现太多文件,要使用hash算法打散存储

* @param filename 文件名,要根据文件名生成存储目录

* @param savePath 文件存储路径

* @return 新的存储目录

*/

private static  String makePath(String filename,String savePath){

    //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址

    int hashcode = filename.hashCode();

    int dir1 = hashcode&0xf;  //0--15

    int dir2 = (hashcode&0xf0)>>4;  //0-15

    //构造新的保存目录

    String dir = savePath + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5

    //File既可以代表文件也可以代表目录

    File file = new File(dir);

    //如果目录不存在

    if(!file.exists()){

        //创建目录

        file.mkdirs();

    }

    return dir;

}

}

1.4 Servlet3.1支持的文件上传

package com.qf.servlet;

import java.io.IOException;

import java.util.Collection;

import javax.servlet.ServletException;

import javax.servlet.annotation.MultipartConfig;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.Part;

import org.apache.commons.io.IOUtils;

import com.qf.utils.FileUploadUtils;

/**

 * Servlet implementation class UploadFileServlet2

 */

@WebServlet("/upLoadfile2")

@MultipartConfig(fileSizeThreshold=1024*100,maxFileSize=1024*1024*2,maxRequestSize=1024*1024*20)

public class UploadFileServlet2 extends HttpServlet {

private static final long serialVersionUID = 1L;

    /**

     * @see HttpServlet#HttpServlet()

     */

    public UploadFileServlet2() {

        super();

        // TODO Auto-generated constructor stub

    }

/**

 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

 */

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 //1乱码

        request.setCharacterEncoding("utf-8");

        response.setContentType("text/html;charset=utf-8");

        String savepath=request.getServletContext().getRealPath("/WEB-INF/upload");

        File dir=new File(savepath);

        if(!dir.exists()){

            dir.mkdirs();

        }

        //2获取多分部集合

        Collection<Part> parts = request.getParts();

        if(parts!=null){

            System.out.println("parts的个数:"+parts.size());

            for (Part part : parts) {

                System.out.println(part.getClass().getName());

                //判断是文件还是普通项

                String filename=part.getSubmittedFileName();

                System.out.println(filename+"-------------");

                if(filename!=null){

                    //文件

                    if(filename.trim().length()==0){

                        continue;

                    }

                    //获取真实的文件名:解决IE文件名的问题,兼容chrome

                    String dis= part.getHeader("Content-Disposition");

                    String realfilename=dis.substring(dis.lastIndexOf("filename=")+10,dis.length()-1);

                    realfilename=realfilename.substring(realfilename.lastIndexOf("\\")+1);

                    List<String> list= Arrays.asList(".jpg",".png",".bmp");

                    String ext=realfilename.substring(realfilename.lastIndexOf("."));

                    if(!list.contains(ext)){

                        response.getWriter().write("您上传的文件类型不支持");

                        continue;

                    }

                    //生成带uuid文件名

                    String uuidfilename=UpLoadUtils.createNewFileName(realfilename);

                    //分散存储

                    String newpath=UpLoadUtils.createNewPath(savepath, realfilename);

                    //保存文件

                    part.write(newpath+"/"+uuidfilename);

                    response.getWriter().write("上传成功:"+realfilename);

                    part.delete();//删除缓存文件

                }else{

                    //普通项

                    String name=part.getName();

                    String value = request.getParameter(name);

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

                }

            }

        }

    }

/**

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

}

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!