文件上传和下载

文件的上传和下载

文件上传

文件上传的三要素
  • 提供form表单,method必须是post
  • form表单的enctype必须是multipart/form-data
  • 提供 input type = “file” 类型输入
文件上传注意的细节
  1. 为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放在WEB-INF下。
  2. 为了防止文件覆盖的现象发生,要为上传的文件产生一个唯一的文件名。
  3. 为防止一个目录下出现太多文件,要使用hash打乱算法存储
  4. 要限制上传文件的最大值
  5. 要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法
实现文件上传

1.编写上传页面form表单

<form id="form1" action="${pageContext.request.contextPath }/upfileservlet" method="post" enctype="multipart/form-data">
        用户名:<input type="text" name="username" /><br>
        电话:<input type="text" name="telphone" /><br>
        文件:<input type="file" name="file" /><br>
    <input type="button" value="再添加一张图片" onclick="addfile(this)"><br/>
        <input type="submit" value="提交" />

    </form>
    <script type="text/javascript">
        var num=2;
        function addfile(obj){
            //alert("xxx");
            //dom操作
            //添加div
            var div1=document.createElement("div");
            //添加input标签
            var inputfile=document.createElement("input");
            inputfile.type="file";
            inputfile.name="myfile"+num;
            num++;
            //添加删除按钮
            var del=document.createElement("input");
            del.type="button";
            del.value="删除";
            del.onclick=function(){
                this.parentNode.remove();

            };

            div1.append(inputfile);
            div1.append(del);

            var form1=document.getElementById("form1");
            form1.insertBefore(div1,obj);

        }


    </script>

2.编写servlet处理界面

    /**
     * 处理文件上传的方法
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");

        // 得到上传路径,将上传的路径放入WEB-INF下,不予许外界访问,保证上传文件的安全性
        String path = request.getServletContext().getRealPath("WEB-INF//upload");

        File file = new File(path);
        // 如果文件不存在就创建
        if (!file.exists()) {
            file.mkdirs();
        }

        // 创建DiskFileItemFactory工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();

        // 设置工厂缓冲大小
        factory.setSizeThreshold(1024 * 100);// 默认为10K
        // 设置上传文件的缓存目录
        // factory.setRepository(repository);

        // 创建一个文件解析器
        ServletFileUpload upload = new ServletFileUpload(factory);

        // 解决中文乱码问题
        upload.setHeaderEncoding("utf-8");
        // 监听上传文件的进度
        upload.setProgressListener(new ProgressListener() {

            @Override
            public void update(long arg0, long arg1, int arg2) {
                System.out.println("文件大小为:" + arg1 + ",当前已处理:" + arg0 + ",序号:" + arg2);

            }
        });

        // 判断提交的数据是不是表单数据
        if (ServletFileUpload.isMultipartContent(request)) {
            try {
                // 设置上传单个文件的大小
                upload.setFileSizeMax(1024 * 100);// 大小为100KB
                // 设置所有文件总量的最大值
                upload.setSizeMax(1024 * 1024 * 10);// 大小为10M

                // 解析数据,放回一个list集合,存放数据项
                List<FileItem> fileItems = upload.parseRequest(request);
                for (FileItem fileItem : fileItems) {

                    // 判断是不是普通输入项的数据
                    if (fileItem.isFormField()) {
                        // 获得数据项的名字
                        String name = fileItem.getFieldName();
                        String value = fileItem.getString("utf-8");
                        System.out.println(name + "..." + value);
                    } else {// 封装的是文件

                        // 得到上传文件的名字
                        String name = fileItem.getName();

                        // 如果文件名为空
                        if (name == null || name.trim().equals("")) {
                            continue;
                        }

                        // 不同的浏览器传入的名字可能存在路径,解决文件名带有路径问题
                        String filename = name.substring(name.lastIndexOf("\\") + 1);
//控制文件传的类型
                        String ext = filename.substring(filename.lastIndexOf(".")+1);
                        if (!UUIDUtils.exts.contains(ext)) {
                            response.getWriter().write("文件类型不支持");
                            return;
                        }

                        // 调用工具类,得到唯一标识
                        String fileName = UUIDUtils.getFileName(filename);
                        // 调用工具类,得到目录
                        String newPath = UUIDUtils.makeFilePath(filename, path);

                        // 获得输入流
                        InputStream is = fileItem.getInputStream();
                        FileOutputStream fos = new FileOutputStream(newPath + "\\" + fileName);
                        // 写入硬盘
                        byte[] bs = new byte[1024];
                        int len = 0;
                        while ((len = is.read(bs)) != -1) {
                            fos.write(bs, 0, len);
                        }
                        // 关流
                        fos.close();
                        is.close();
                        // 删除文件上传时生成的临时文件
                        fileItem.delete();
                        System.out.println("文件上传成功");
                    }
                }

            } catch (FileUploadException e) {

                e.printStackTrace();
                System.out.println("文件上传失败");
            }

        } else {
            // 正常处理
            // request.getParameter("username");
        }

    }

3.编写工具类

/**
 * uuid工具类
 * @author 15216
 *
 */
public class UUIDUtils {
    //创建集合存储文件的类型
    public static List<String> exts;
    //静态代码块初始化文件的类型
    static {
        exts = new ArrayList<String>();
        //exts.add(".jpg");
        exts.add(".png");
        exts.add(".zip");
    }

    public static String getFileName(String filename) {

        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        return uuid+"_"+filename;
    }

    public static String makeFilePath(String filename,String filepath) {
        //得到字符串的hascode值
        int code = filename.hashCode();

        //0x十六进制前缀
        int  dir1 = code&0xf;//得到后四位二进制数
        int code1 = code>>4;//右移四位
        int dir2=code1&0xf;//得到后八位的前四位

        String path = filepath+"\\"+dir1+"\\"+dir2;
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        return path;
    }
}
servlet3.0支持的文件上传

代码实现


//注解配置文件上传的最大值
@MultipartConfig(fileSizeThreshold=1024*1024,maxFileSize=1024*100,maxRequestSize=1024*1024 )

/**
 * servlet3.0
 */ 
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置编码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //获取路径
        String path = request.getServletContext().getRealPath("WEB-INF//upload");
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }

        //接收数据
        Collection<Part> parts = request.getParts();
        if (parts!=null) {
            for (Part part : parts) {
                //获取文件名
                String fileName = part.getSubmittedFileName();
                //如果为空不是文件
                if (fileName!=null) {//是文件
                    if (fileName.trim().equals("")) {
                    continue;
                    }

                    //form-data; name="myfile1"; filename="D:\图片\timg.jpg"
                    String header = part.getHeader("content-disposition");
                    System.out.println(header);
                    String name1 = header.split("; ")[2];//filename="D:\图片\timg.jpg"
                    System.out.println(name1);//"D:\图片\timg.jpg"
                    String name2 = name1.substring(name1.indexOf("\"")+1, name1.length()-1);
                    fileName = name2.substring(name2.lastIndexOf("\\")+1);

                    System.out.println(fileName);

                    //为文件名产生一个唯一标识
                    String filename = UUIDUtils.getFileName(fileName);
                    String filepath = UUIDUtils.makeFilePath(filename, path);

                    part.write(filepath+"\\"+filename);
                    System.out.println("文件上传成功");

                }else {
                    //获取普通数据的名字
                    String name = part.getName();
                    String value = request.getParameter(name);
                    System.out.println(name+"..."+value);
                }
            }
        }
    }

文件下载

思想:首先需要编写一个ListFileServleDt列出文件目录下的所有的文件,在jsp文件中提供超链接的方式给用户进行下载操作,然后编写DownServlet实现下载操作。
编写ListFileServlet


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取文件路径
        String path = request.getServletContext().getRealPath("WEB-INF//upload");
        File file = new File(path);
        Map<String, String> map = new HashMap<String, String>();
        listFile(file, map);

        //将集合放入request中
        request.setAttribute("map", map);
        //转发到列表jsp,数据不会丢失
        request.getRequestDispatcher("/listfile.jsp").forward(request, response);

    }
    /**
     * 通过递归将目标目录下的文件全部存到map集合中
     * @param dir
     * @param map
     */
    public void listFile(File dir,Map<String, String> map) {
        File[] files = dir.listFiles();
        if (files!=null) {
            for (File file : files) {
                //判断是不是目录
                if (file.isDirectory()) {
                    listFile(file, map);
                }else {
                    //得到文件的名字
                    String uuid_name = file.getName();//uuid_xxx.jpg
                    //截取文件的名字
                    String realname = uuid_name.substring(uuid_name.indexOf("_")+1);
                    //将得到文件的名字作为key值,将realname作为值存入集合
                    map.put(uuid_name, realname);
                }

            }
        }
    }
编写listfile.jsp页面
<body>  
    <h2>下载</h2>
    <c:forEach items="${map }" var="entry">
    <!-- 创建一个地址,并放入域中 1、URL重写2、中文编码 -->
        <c:url var="myurl" value="/downfileservlet">
            <c:param name="filename" value="${entry.key }"></c:param>
        </c:url>
        ${entry.value } <a href="${myurl }">下载</a>
    </c:forEach>
</body>
编写downFileServlet

    /**
     * 文件下载
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置编码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        //接收要下载的文件名
        String filename = request.getParameter("filename");

        //得到路径名
        String path = request.getServletContext().getRealPath("WEB-INF//upload");

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

        }


        //获取文件在upload中的位置
        String name = filename.substring(filename.indexOf("_")+1);
        //传入的是包含唯一编码的文件名
        String filepath = UUIDUtils.makeFilePath(filename, path);

        File file = new File(filepath+"\\"+filename);
        System.out.println(file);
        if (!file.exists()) {
            response.getWriter().write("文件不存在");
            return;
        }


        //设置头
        response.setHeader("content-disposition", "attachment;filename"+URLDecoder.decode(name,"utf-8"));
        ServletOutputStream os = response.getOutputStream();
        FileInputStream fis = new FileInputStream(file);

        int len = 0;
        byte[] bs = new byte[1024];
        while((len = fis.read(bs))!=-1) {
            os.write(bs,0,len);
        }
        fis.close();


    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值