• 使用 fileupload 组件完成文件的上传应用


    1. 使用 fileupload 组件完成文件的上传应用

    commons-dbutils-1.3.jar
    commons-fileupload-1.2.1.jar

    1). 需求:

    > 在 upload.jsp 页面上使用 jQuery 实现 "新增一个附件", "删除附件". 但至少需要保留一个.

    > 对文件的扩展名和文件的大小进行验证. 以下的规则是可配置的. 而不是写死在程序中的.

       ①文件的扩展名必须为 .pptx, docx, doc
       ② 每个文件的大小不能超过 1 M
       ③ 总的文件大小不能超过 5 M.

    upload.properties

    exts=pptx,docx,doc
    file.max.size=1048576
    total.file.max.size=5242880

    > 若验证失败, 则在 upload.jsp 页面上显示错误消息:

      ① 若某一个文件不符合要求: xxx 文件扩展名不合法 或 xxx 文件大小超过 1 M
      ② 总的文件大小不能超过 5 M.

    > 若验证通过, 则进行文件的上传操作

       ① 文件上传, 并给一个不能和其他文件重复的名字, 但扩展名不变
       ② 在对应的数据表中添加一条记录.
            id file_name file_path file_desc

    FileUploadServlet.java

    package com.aff.fileupload.app.servlet;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.UnsupportedEncodingException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    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.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;mport com.aff.fileupload.app.bean.FileUploadBean;
    import com.aff.fileupload.app.db.UploadFileDao;
    import com.aff.fileupload.app.exception.InvalidExtNameException;
    import com.aff.fileupload.app.utils.FileUploadAppProperties;
    import com.aff.fileupload.app.utils.FileUtils;
    
    @WebServlet("/app/fileuploadservlet")
    public class FileUploadServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        private static final String FILE_PATH = "/WEB-INF/files/";
    
        private static final String TEMP_DIR = "d:\tempDirectory";
    
        private UploadFileDao dao = new UploadFileDao();
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            request.setCharacterEncoding("UTF-8");
    
            String path = null;
    
            // 获取 ServletFileUpload 对象.
            ServletFileUpload upload = getServletFileUpload();
    
            try {
    
                // 把需要上传的 FileItem 都放入到该 Map 中
                // 键: 文件的待存放的路径, 值: 对应的 FileItem 对象
                Map<String, FileItem> uploadFiles = new HashMap<String, FileItem>();
    
                // 解析请求, 得到 FileItem 的集合.
                List<FileItem> items = upload.parseRequest(request);
    
                // 1. 构建 FileUploadBean 的集合, 同时填充 uploadFiles
                List<FileUploadBean> beans = buildFileUploadBeans(items, uploadFiles);
    
                // 2. 校验扩展名:
                vaidateExtName(beans);
    
                // 3. 校验文件的大小: 在解析时, 已经校验了, 我们只需要通过异常得到结果.
    
                // 4. 进行文件的上传操作.
                upload(uploadFiles);
    
                // 5. 把上传的信息保存到数据库中
                saveBeans(beans);
    
                // 6. 删除临时文件夹的临时文件
                FileUtils.delAllFile(TEMP_DIR);
    
                path = "/app/success.jsp";
    
            } catch (Exception e) {
                e.printStackTrace();
                path = "/app/upload.jsp";
                request.setAttribute("message", e.getMessage());
            }
    
            request.getRequestDispatcher(path).forward(request, response);
        }
    
        private void saveBeans(List<FileUploadBean> beans) {
            dao.save(beans);
        }
    
        /**
         * 文件上传前的准备工作. 得到 filePath 和 InputStream
         * 
         * @param uploadFiles
         * @throws IOException
         */
        private void upload(Map<String, FileItem> uploadFiles) throws IOException {
            for (Map.Entry<String, FileItem> uploadFile : uploadFiles.entrySet()) {
                String filePath = uploadFile.getKey();
                FileItem item = uploadFile.getValue();
    
                upload(filePath, item.getInputStream());
            }
        }
    
        /**
         * 文件上传的 IO 方法.
         * 
         * @param filePath
         * @param inputStream
         * @throws IOException
         */
        private void upload(String filePath, InputStream inputStream) throws IOException {
            OutputStream out = new FileOutputStream(filePath);
    
            byte[] buffer = new byte[1024];
            int len = 0;
    
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
    
            inputStream.close();
            out.close();
    
            System.out.println(filePath);
        }
    
        /**
         * 校验扩展名是否合法
         * 
         * @param beans:
         */
        private void vaidateExtName(List<FileUploadBean> beans) {
            String exts = FileUploadAppProperties.getInstance().getProperty("exts");
            List<String> extList = Arrays.asList(exts.split(","));
            System.out.println(extList);
    
            for (FileUploadBean bean : beans) {
                String fileName = bean.getFileName();
                System.out.println(fileName.indexOf("."));
    
                String extName = fileName.substring(fileName.lastIndexOf(".") + 1);
                System.out.println(extName);
    
                if (!extList.contains(extName)) {
                    throw new InvalidExtNameException(fileName + "文件的扩展名不合法");
                }
            }
        }
    
        /**
         * 利用传入的 FileItem 的集合, 构建 FileUploadBean 的集合, 同时填充 uploadFiles
         * 
         * FileUploadBean 对象封装了: id, fileName, filePath, fileDesc uploadFiles:
         * Map<String, FileItem> 类型, 存放文件域类型的 FileItem. 键: 待保存的文件的名字 ,值: FileItem 对象
         * 
         * 构建过程: 1. 对传入 FileItem 的集合进行遍历. 得到 desc 的那个 Map. 键: desc 的
         * fieldName(desc1, desc2 ...). 值: desc 的那个输入的文本值
         * 
         * 2. 对传入 FileItem 的集合进行遍历. 得到文件域的那些 FileItem 对象, 构建对应的 key (desc1 ....)
         * 来获取其 desc. 构建的 FileUploadBean 对象, 并填充 beans 和 uploadFiles
         * 
         * @param items
         * @param uploadFiles
         * @return
         * @throws UnsupportedEncodingException
         */
        private List<FileUploadBean> buildFileUploadBeans(List<FileItem> items, Map<String, FileItem> uploadFiles)
                throws UnsupportedEncodingException {
            List<FileUploadBean> beans = new ArrayList<>();
    
            Map<String, String> descs = new HashMap<>();
    
            for (int i = 0; i < items.size(); i++) {
                FileItem item = items.get(i);
    
                if (item.isFormField()) {
                    // desc1 或 desc2 ...
                    String fieldName = item.getFieldName();
                    String desc = item.getString("UTF-8");
    
                    descs.put(fieldName, desc);
                }
            }
    
            for (int i = 0; i < items.size(); i++) {
                FileItem item = items.get(i);
                FileUploadBean bean = null;
                if (!item.isFormField()) {
                    String fieldName = item.getFieldName();
                    String descName = "desc" + fieldName.substring(fieldName.length() - 1);
                    String desc = descs.get(descName);
    
                    // 对应文件名
                    String fileName = item.getName();
                    String filePath = getFilePath(fileName);
    
                    bean = new FileUploadBean(fileName, filePath, desc);
                    beans.add(bean);
    
                    uploadFiles.put(bean.getFilePath(), item);
                }
            }
    
            return beans;
        }
    
        /**
         * 根据跟定的文件名构建一个随机的文件名 1. 构建的文件的文件名的扩展名和给定的文件的扩展名一致 2. 利用 ServletContext 的
         * getRealPath 方法获取的绝对路径 3. 利用了 Random 和 当前的系统时间构建随机的文件的名字
         * 
         * @param fileName
         * @return
         */
        private String getFilePath(String fileName) {
            String extName = fileName.substring(fileName.lastIndexOf("."));
            Random random = new Random();
    
            String filePath = getServletContext().getRealPath(FILE_PATH) + "\" + System.currentTimeMillis()
                    + random.nextInt(100000) + extName;
            return filePath;
        }
    
        /**
         * 构建 ServletFileUpload 对象 从配置文件中读取了部分属性, 用户设置约束. 该方法代码来源于文档.
         * 
         * @return
         */
        private ServletFileUpload getServletFileUpload() {
            String fileMaxSize = FileUploadAppProperties.getInstance().getProperty("file.max.size");
            String totalFileMaxSize = FileUploadAppProperties.getInstance().getProperty("total.file.max.size");
    
            DiskFileItemFactory factory = new DiskFileItemFactory();
    
            factory.setSizeThreshold(1024 * 500);
            File tempDirectory = new File(TEMP_DIR);
            factory.setRepository(tempDirectory);
    
            ServletFileUpload upload = new ServletFileUpload(factory);
    
            upload.setSizeMax(Integer.parseInt(totalFileMaxSize));
            upload.setFileSizeMax(Integer.parseInt(fileMaxSize));
    
            return upload;
        }
    }

    upload.jsp

    <%@ 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>
    <script type="text/javascript"
        src="${pageContext.request.contextPath }/scripts/jquery-1.12.3.js"></script> 
    <script type="text/javascript">
        
        $(function(){
            var i = 2;
            $("#addFile").click(function(){
                $(this).parent().parent().before("<tr class='file'><td>File" 
                        + i + ":</td><td><input type='file' name='file" 
                        + i + "'/></td></tr>"
                        + "<tr class='desc'><td>Desc" 
                        + i + ":</td><td><input type='text' name='desc" 
                        + i + "'/><button id='delete" 
                        + i + "'>删除</button></td></tr>");
                i++;
                
                //获取新添加的删除按钮
                $("#delete" + (i-1)).click(function(){
                    var $tr = $(this).parent().parent();
                    $tr.prev("tr").remove();
                    $tr.remove();
                    
                    //对 i 重写排序
                    $(".file").each(function(index){
                        var n = index + 1;
                        
                        $(this).find("td:first").text("File" + n);
                        $(this).find("td:last input").attr("name", "file" + n);
                    });
                    
                    $(".desc").each(function(index){
                        var n = index + 1;
                        
                        $(this).find("td:first").text("Desc" + n);
                        $(this).find("td:last input").attr("name", "desc" + n);
                    });
                
                    i = i - 1;
                });
            
                return false;
            });
            
        });
        
    </script>
    
    </head>
    <body>
    
        <font color="red">${message }</font>
        <br><br>
        
        <form action="fileuploadservlet" method="post" enctype="multipart/form-data">
            
            <table>
                <tr class="file">
                    <td>File1:</td>
                    <td><input type="file" name="file1"/></td>
                </tr>
                <tr class="desc">
                    <td>Desc1:</td>
                    <td><input type="text" name="desc1"/></td>
                </tr>
                
                <tr>
                    <td><input type="submit" id="submit" value="提交"/></td>
                    <td><button id="addFile">新增一个附件</button></td>
                </tr>
            </table>
            
        </form>
    </body>
    </html>

    FileUploadAppListener.java

    package com.aff.fileupload.app.listener;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Map;
    import java.util.Properties;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    import com.aff.fileupload.app.utils.FileUploadAppProperties;
    
    @WebListener
    public class FileUploadAppListener implements ServletContextListener {
    
        public FileUploadAppListener() {
        }
    
        public void contextInitialized(ServletContextEvent sce) {
            InputStream is = getClass().getClassLoader().getResourceAsStream("upload.properties");
            Properties properties = new Properties();
    
            try {
                properties.load(is);
    
                for (Map.Entry<Object, Object> prop : properties.entrySet()) {
                    String propertyName = (String) prop.getKey();
                    String propertyValue = (String) prop.getValue();
    
                    FileUploadAppProperties.getInstance().addProperty(propertyName, propertyValue);
    
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public void contextDestroyed(ServletContextEvent sce) {
        }
    }

    UploadFileDao.java

    package com.aff.fileupload.app.db;
    
    import java.sql.Connection;
    import java.util.List;
    
    import com.aff.fileupload.app.bean.FileUploadBean;
    
    public class UploadFileDao extends DAO<FileUploadBean> {
    
        public List<FileUploadBean> getFiles() {
    
            Connection conn = null;
    
            try {
                conn = JDBCUtils.getConnection();
                String sql = "SELECT id, file_name fileName, file_path filePath, " + "file_desc fileDesc FROM upload_files";
                return getForList(conn, sql);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(conn);
            }
            return null;
        }
    
        public void save(List<FileUploadBean> uploadFiles) {
    
            Connection conn = null;
    
            try {
                conn = JDBCUtils.getConnection();
                String sql = "INSERT INTO upload_files (file_name, file_path, file_desc) VALUES " + "(?, ?, ?)";
                for (FileUploadBean file : uploadFiles) {
                    update(conn, sql, file.getFileName(), file.getFilePath(), file.getFileDesc());
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(conn);
            }
        }
    }

    FileUploadBean.java

    package com.aff.fileupload.app.bean;
    
    public class FileUploadBean {
    
        private Integer id;
        private String fileName;
        private String filePath;
        private String fileDesc;
        public FileUploadBean() {
            super();
        }
        public FileUploadBean(String fileName, String filePath, String fileDesc) {
            super();
            this.fileName = fileName;
            this.filePath = filePath;
            this.fileDesc = fileDesc;
        }
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getFileName() {
            return fileName;
        }
        public void setFileName(String fileName) {
            this.fileName = fileName;
        }
        public String getFilePath() {
            return filePath;
        }
        public void setFilePath(String filePath) {
            this.filePath = filePath;
        }
        public String getFileDesc() {
            return fileDesc;
        }
        public void setFileDesc(String fileDesc) {
            this.fileDesc = fileDesc;
        }    
    }

    目录

    2. 如何修改小工具或框架的源代码 ?

    1). 原则: 能不修改就不修改.

    2). 修改的方法:

    > 修改源代码, 替换 jar 包中对应的 class 文件. 
    > 在本地新建相同的包, 和类, 在这个类中修改即可.

    3. 文件的下载:

    DownloadServlet.java

    package com.aff.download.servlet;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URLEncoder;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/downloadServlet")
    public class DownloadServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    //I. 设置 contentType 响应头: 设置响应的类型是什么 ? 通知浏览器是个下载的文件 response.setContentType(
    "application/x-msdownload"); String fileName = "文件下载.pptx";
    //II. 设置 Content-Disposition 响应头: 通知浏览器不再有浏览器来自行处理(或打开)要下载的文件,
    // 而由用户手工完成
    response.setHeader(
    "Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
    //III. 具体的文件: 可以调用 response.getOutputStream 的方式, 以 IO 流的方式发送给客户端. OutputStream out
    = response.getOutputStream(); String pptFileName = "C:\Users\lz\Desktop\NEW\PPT\MAPP.pptx"; InputStream in = new FileInputStream(pptFileName); byte[] buffer = new byte[1024]; int len = 0; while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } in.close(); } }

    download.jsp

    <body>
        <!-- 静态下载 -->
        <a href="xyz.txt">download xyz.txt</a>
        <br>
        <br> 
        <a href="test.jsp">download test.jsp</a>
        <br>
        <br>
        <a href="downloadServlet">DownLoad abcd.pptx</a>
    </body>
    All that work will definitely pay off
  • 相关阅读:
    设计模式之第14章-命令模式(Java实现)
    设计模式之第13章-职责链模式(Java实现)
    设计模式之第12章-享元模式(Java实现)
    我的一年,过去,现在
    Reporting Services 的一些问题
    利用ICSharpCode进行压缩和解压缩
    利用System.Net.Mail 发送邮件
    利用Log4net组件记录日志
    系统权限的设计之简单设计
    利用NPOI组件产Excel完整操作
  • 原文地址:https://www.cnblogs.com/afangfang/p/12822141.html
Copyright © 2020-2023  润新知