Java Web总结十八文件的上传和下载

一、实现Web开发中的文件上传功能,需完成如下两步操作:

  1、在web页面中添加上传输入项。

  2、在Servlet中读取上传文件的数据,并保存到本地硬盘中。

二、如何在web页面中添加上传输入项?

  1、<input type="file">标签用于在web页面中添加文件上传输入项,设置文件上传输入项时须注意:

    1)必须设置input输入项的name属性,否则浏览器将不会发送上传文件的数据。

    2)必须把form的enctype属性值设为multipart/form-data。设置该值后,浏览器在上传文件时,将把文件数据附带在http请求消息体中,并使用MIME协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理。

三、在web开发中实现文件上传功能,通常使用commons-fileupload组件实现。使用commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:

  1、commons-fileupload-1.3.1.jar

  2、commons-io-2.4.jar

四、上传文件的细节:

  1、中文乱码的问题

    1)普通字段的中文乱码问题:FileItem.getString("UTF-8"),FileItem表示上传表单中的表单项内容。

    2)上传字段的中文乱码问题:ServletUploadFile.setHeaderEncoding("UTF-8");

  2、临时文件的删除问题

    1)通过FileItem.delete()

    2)一定要在关闭IO流之后

  3、在同一个目录下上传相同文件名的问题

    1)将文件名拼接一个唯一标识符,即UUID

  4、单个目录下文件过多的问题

    1)采用位运算解决单个目录文件过多

    2)思路:Java Web总结十八文件的上传和下载

  5、为安全将上传的文件放入客户端无法直接访问的目录中的问题

    1)将上传的文件,放置到/WEB-INF/upload/目录下

  6、重构思想

    1)做到重用性

  7、自定义封装上传文件工具类的问题

  8、上传文件的大小问题

  9、上传多个文件的问题

  10、上传多个文件的界面问题

五、显示下载文件列表

  1)递归方式查询可供下载的文件,一定要有出口条件。

  2)使用Map<UUID文件名,真实文件名>收集可供下载的文件

  3)使用<c:url>和<c:param>对中文名进行URL编码

六、下载文件

  1、对传过来的中文编码进行URL解码

  2、通过UUID文件名,反向查到该文件所在的真实目录

七、文件上传下载与数据库结合

  1、在将上传文件保存的同时,写往数据库表,一个上传文件对应一条记录,确保uuidFileName双方一致。

八、上传和下载代码

1、文件目录图

Java Web总结十八文件的上传和下载Java Web总结十八文件的上传和下载

2、UpDao.java

package com.gnnuit.web.dao;

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;

import com.gnnuit.web.domain.Up;
import com.gnnuit.web.util.JdbcUtil;

//向数据库添加up对象
public class UpDao {
    public void addUp(Up up) throws SQLException {
        QueryRunner qr = new QueryRunner(JdbcUtil.getDataSource());
        String sql = "insert into up(username,realFileName,uuidFileName) values(?,?,?)";
        qr.update(sql, new Object[] { up.getUsername(), up.getRealFileName(),
                up.getUuidFileName() });
    }
}

3、Up.java

package com.gnnuit.web.domain;

public class Up {
    private int id;
    private String username;
    private String realFileName;
    private String uuidFileName;

    public Up() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getRealFileName() {
        return realFileName;
    }

    public void setRealFileName(String realFileName) {
        this.realFileName = realFileName;
    }

    public String getUuidFileName() {
        return uuidFileName;
    }

    public void setUuidFileName(String uuidFileName) {
        this.uuidFileName = uuidFileName;
    }
}

4、User.java

package com.gnnuit.web.domain;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.fileupload.FileItem;

//封装上传文件的内容
public class User {
    // 上传用户
    private String username;
    // 上传的文件
    private List<FileItem> upfileList = new ArrayList<FileItem>();

    public User() {
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public List<FileItem> getUpfileList() {
        return upfileList;
    }

    public void setUpfileList(List<FileItem> upfileList) {
        this.upfileList = upfileList;
    }
}

5、NoUpfileException.java

package com.gnnuit.web.exception;

public class NoUpfileException extends Exception{

    private static final long serialVersionUID = 1L;

}

6、UpfileSizeException.java

package com.gnnuit.web.exception;

public class UpfileSizeException extends Exception{


    private static final long serialVersionUID = 1L;

}

7、UpfileTypeException.java

package com.gnnuit.web.exception;

public class UpfileTypeException extends Exception{

    private static final long serialVersionUID = 1L;

}

8、DownLoadServlet.java

package com.gnnuit.web.servlet.download;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gnnuit.web.util.UploadUtil;

public class DownLoadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取传过来的UUID文件名,参数带有中文,需要做处理
        String uuidFileName = request.getParameter("fileName");
        byte[] buf = uuidFileName.getBytes("ISO8859-1");
        uuidFileName = new String(buf, "UTF-8");

        // 根据UUID文件名获取真实文件名
        int index = uuidFileName.lastIndexOf("_");
        String realFileName = uuidFileName.substring(index + 1);

        // 设置弹出下载框
        String uploadPath = this.getServletContext().getRealPath(
                UploadUtil.uploadPath);
        String uuidFilePath = UploadUtil.makeUuidFilePath(uploadPath,
                uuidFileName);
        response.setHeader("Content-Disposition", "attachment; filename="
                + URLEncoder.encode(realFileName, "UTF-8"));

        // 开始下载
        FileInputStream fis = new FileInputStream(new File(uuidFilePath + "/"
                + uuidFileName));
        OutputStream out = response.getOutputStream();
        int len = 0;
        buf = new byte[1024];
        while ((len = fis.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        fis.close();
        out.close();
    }

}

9、FileListServlet.java

package com.gnnuit.web.servlet.download;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gnnuit.web.util.UploadUtil;

public class FileListServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String uploadPath = this.getServletContext().getRealPath(
                UploadUtil.uploadPath);
        Map<String, String> map = new HashMap<>();// key代表UUID文件名,value代表真实文件名
        getFiles(uploadPath, map);
        request.setAttribute("map", map);
        request.getRequestDispatcher("/download.jsp")
                .forward(request, response);
    }

    // 获取下载目录的所有文件
    private void getFiles(String uploadPath, Map<String, String> map) {
        File file = new File(uploadPath);
        if (file.isFile()) {
            // 是文件,不是目录
            String uuidFileName = file.getName();
            int index = uuidFileName.lastIndexOf("_");
            String realFileName = uuidFileName.substring(index + 1);
            map.put(uuidFileName, realFileName);
        } else {
            // 是目录
            File[] files = file.listFiles();
            for (File f : files) {
                getFiles(f.getPath(), map);
            }
        }
    }

}

10、UploadServlet.java

package com.gnnuit.web.servlet.upload;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gnnuit.web.dao.UpDao;
import com.gnnuit.web.domain.Up;
import com.gnnuit.web.domain.User;
import com.gnnuit.web.exception.NoUpfileException;
import com.gnnuit.web.exception.UpfileSizeException;
import com.gnnuit.web.exception.UpfileTypeException;
import com.gnnuit.web.util.UploadUtil;

public class UploadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            User user = UploadUtil.doUpload(request);
            String uploadPath = this.getServletContext().getRealPath(
                    UploadUtil.uploadPath);
            List<Up> upList = new ArrayList<>();
            // 写入硬盘
            UploadUtil.doSave(user, uploadPath, upList);
            //写入数据库
            UpDao dao = new UpDao();
            for (Up up : upList) {
                dao.addUp(up);
            }
            request.setAttribute("message", "上传文件成功");
            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(
                    request, response);
        } catch (UpfileSizeException e) {
            e.printStackTrace();
            request.setAttribute("message", "上传文件大小限制在200K以内");
            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(
                    request, response);
        } catch (UpfileTypeException e) {
            e.printStackTrace();
            request.setAttribute("message", "只能上传JPG格式的文件");
            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(
                    request, response);
        } catch (NoUpfileException e) {
            e.printStackTrace();
            request.setAttribute("message", "无上传文件");
            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(
                    request, response);
        } catch (Exception e) {
            e.printStackTrace();
            request.setAttribute("message", "上传文件失败");
            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(
                    request, response);
        }

    }

}

11、up.sql

use mydb3;
drop table if exists up;
create table if not exists up(
    id int primary key auto_increment,
    username varchar(20) not null,
    realFileName varchar(20) not null,
    uuidFileName varchar(100) not null
);

12、JdbcUtil.java

package com.gnnuit.web.util;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public final class JdbcUtil {
    private static ComboPooledDataSource cpds;
    static {
        cpds = new ComboPooledDataSource();
    }

    // 获取数据源
    public static DataSource getDataSource() {
        return cpds;
    }

    // 取得连接
    public static Connection getMySqlConnection() throws SQLException {
        return cpds.getConnection();
    }

    // 关闭连接
    public static void close(Connection conn) throws SQLException {
        if (conn != null) {
            conn.close();
        }
    }
}

13、UploadUtil.java

package com.gnnuit.web.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.gnnuit.web.domain.Up;
import com.gnnuit.web.domain.User;
import com.gnnuit.web.exception.NoUpfileException;
import com.gnnuit.web.exception.UpfileSizeException;

public final class UploadUtil {
    // 取得上传使用的临时和真实目录
    public static final String tempPath = "/WEB-INF/temp";
    public static final String uploadPath = "/WEB-INF/upload";

    // 取得真实文件名
    public static String getRealFileName(String realFileName) {
        int index = realFileName.lastIndexOf("\\");
        if (index >= 0) {
            // IE6浏览器
            realFileName = realFileName.substring(index + 1);
        }
        return realFileName;
    }

    // 取得uuid文件名
    public static String makeUuidFilePath(String uploadPath, String uuidFileName) {
        String uuidFilePath = null;
        int code = uuidFileName.hashCode();// 8
        int dir1 = code & 0xF;// 3
        int dir2 = code >> 4 & 0xF;// A
        File file = new File(uploadPath + "/" + dir1 + "/" + dir2);
        // 如果该目录未存在
        if (!file.exists()) {
            // 一次性创建N层目录
            file.mkdirs();
        }
        uuidFilePath = file.getPath();
        return uuidFilePath;
    }

    // 取得upload/目录下的分散目录
    public static String makeUuidFileName(String realFileName) {
        return UUID.randomUUID().toString() + "_" + realFileName;
    }

    // 文件复制
    public static void doSave(InputStream is, String uuidFileName,
            String uuidFilePath) {
        OutputStream os = null;
        try {
            os = new FileOutputStream(uuidFilePath + "/" + uuidFileName);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = is.read(buf)) > 0) {
                os.write(buf, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 将上传文件封装成JavaBean对象中
    public static User doUpload(HttpServletRequest request) throws Exception {
        User user = new User();
        // 创建上传文件工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置内存中缓存区的大小,默认10K
        factory.setSizeThreshold(100 * 1024);
        // 设置上传文件临时存放的目录
        String tempPath = request.getSession().getServletContext()
                .getRealPath(UploadUtil.tempPath);
        factory.setRepository(new File(tempPath));
        // 创建上传文件对象[核心]
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 设置上传文件的中文编码方式
        upload.setHeaderEncoding("UTF-8");
        // 客户端上传文件是否使用MIME协议,
        boolean flag = ServletFileUpload.isMultipartContent(request);
        if (!flag) {
            // 不是以MIME协议上传文件
            throw new ServletException();
        } else {
            /*
             * 是以MIME协议上传的文件,解析request中的所有上传内容每个内容封装成一个对象FileItem,
             * FileItem代表普通字段和上传字段二类
             */
            List<FileItem> fileItemList = upload.parseRequest(request);
            for (FileItem fileItem : fileItemList) {
                if (fileItem.isFormField()) {
                    String fieldValue = fileItem.getString("UTF-8");
                    user.setUsername(fieldValue);
                } else {
                    // 必定是上传字段

                    // 如果无上传文件
                    if (fileItem.getSize() == 0) {
                        throw new NoUpfileException();
                    }

                    // 只能上传JPG文件
                    /*String realFileName = UploadUtil.getRealFileName(fileItem
                            .getName());
                    if (!realFileName.endsWith("jpg")) {
                        throw new UpfileTypeException();
                    }*/

                    // 只有上传<=200K的文件
                    if (fileItem.getSize() > 200 * 1024) {
                        throw new UpfileSizeException();
                    }

                    // 封装到JavaBean
                    user.getUpfileList().add(fileItem);

                }
            }// end of for loop
        }
        return user;
    }

    public static void doSave(User user, String uploadPath, List<Up> upList)
            throws Exception {
        // 取得该用户上传的所有文件集合
        List<FileItem> fileItemList = user.getUpfileList();
        // 迭代每个文件,并上传
        for (FileItem fileItem : fileItemList) {
            // 创建Up对象
            Up up = new Up();
            up.setUsername(user.getUsername());
            // 取得输入流
            InputStream is = fileItem.getInputStream();
            // 取得真实文件名
            String realFileName = fileItem.getName();
            realFileName = UploadUtil.getRealFileName(realFileName);
            // 取得UUID文件名
            String uuidFileName = UploadUtil.makeUuidFileName(realFileName);
            // 取得UUID文件路径
            String uuidFilePath = UploadUtil.makeUuidFilePath(uploadPath,
                    uuidFileName);
            // 保存
            UploadUtil.doSave(is, uuidFileName, uuidFilePath);
            // 收集Up信息
            up.setUuidFileName(uuidFileName);
            up.setRealFileName(realFileName);
            upList.add(up);
            // 删除临时文件
            fileItem.delete();
        }

    }
}

14、c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/mydb3</property>
    </default-config>
</c3p0-config>

15、message.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  
  <body>
    ${message }
  </body>
</html>

16、download.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  
  <body>
    <table align="center" border="1">
        <tr>
            <th>文件列表</th>
            <th>操作</th>
        </tr>
        <c:forEach var="entry" items="${map }">
            <tr>
                <td>${entry.value }</td>
                <td>
                    <c:url var="myURL" value="/DownLoadServlet">
                        <c:param name="fileName" value="${entry.key }"></c:param>
                    </c:url>
                    <a href="${myURL }" >下载</a>
                </td>
            </tr>
        </c:forEach>
    </table>
  </body>
</html>

17、upload.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
      <script type="text/javascript">
          var time=0;
          function addDiv(addButton) {
            var outDiv=document.getElementById("outDiv");
            var divElement= document.createElement("div");
            var inputElement=document.createElement("input");
            inputElement.type="file";
            inputElement.name="filename";
            var inputElement2=document.createElement("input");
            inputElement2.type="button";
            inputElement2.value="删除";
            inputElement2.onclick=function(){
                var parentNode= this.parentNode.parentNode;
                parentNode.removeChild(this.parentNode);
                time--;
                if(time<5){
                    addButton.disabled=false;
                }
            };
            divElement.appendChild(inputElement);
            divElement.appendChild(inputElement2);
            outDiv.appendChild(divElement);
            time++;
            if(time==5){
                addButton.disabled=true;
            }
        }
      </script>
  </head>
  <body>
    <form action="${pageContext.request.contextPath }/UploadServlet" method="post" enctype="multipart/form-data">
        <table border="1" align="center">
            <tr>
                <td>上传用户</td>
                <td><input type="text" name="username"/></td>
            </tr>
            <tr>
                <td>上传文件</td>
                <td>
                    <div id="outDiv">
                    
                    </div>
                    <%--<input type="file" name="filename"/> --%>
                    <input type="button" value="添加" onclick="addDiv(this)"/>
                </td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <input type="submit" value="提交"/>
                </td>
            </tr>
            
            <tr>
                <td colspan="2" align="center">
                    <a href="${pageContext.request.contextPath }/FileListServlet">显示下载文件列表</a>
                </td>
            </tr>
        </table>
    </form>
  </body>
</html>

 

Java Web总结十八文件的上传和下载,布布扣,bubuko.com

Java Web总结十八文件的上传和下载

上一篇:微信小程序版2048


下一篇:HTML5仿微信聊天界面、微信朋友圈实例