JavaWeb(六) IO流实现文件上传下载

最近学的东西有点杂,做了和看了写什么就把它记录下来。不得不说代码真的很神奇,需要学习的还很多。

一直没把文件上传和下载搞清楚,今天就来动手写一写。

一 、依赖如下两Jar实现的文件上传。

实现代码如下:

基础实现:

 1 package com.qq.upload;
 2
 3 import org.apache.commons.fileupload.FileItem;
 4 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 5 import org.apache.commons.fileupload.servlet.ServletFileUpload;
 6
 7 import javax.servlet.ServletException;
 8 import javax.servlet.annotation.WebServlet;
 9 import javax.servlet.http.HttpServlet;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletResponse;
12 import java.io.*;
13 import java.util.List;
14 @WebServlet("/doUpload")
15 public class Upload  extends HttpServlet {
16
17     public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
18         //得到上传文件的保存目录,将上传的文件存放在WEB-INF目录下面 不允许外界直接访问,保证上传文件的安全性
19 /*        String savePath  = this.getServletContext().getRealPath("/WEB-INF/upload");*/
20         String savePath = this.getServletContext().getRealPath("/LoadJsp");
21         File file  =new File(savePath);
22         if(!file.exists()&&!file.isDirectory()){
23             System.out.println(savePath+"目标目录不存在,需要进行创建");
24             file.mkdir();
25
26         }
27         String message = null;
28         try {
29             //1 创建DiskFileItemFactory工厂
30             DiskFileItemFactory factory = new DiskFileItemFactory();
31             //2 创建一个文件上传解析器
32             ServletFileUpload upload = new ServletFileUpload(factory);
33             //判断提交上来的数据是不是表单上的数据
34             upload.setHeaderEncoding("UTF-8");
35             if (!ServletFileUpload.isMultipartContent(req)) {
36                 return;
37             }
38
39             //4 使用ServletFileUpload解析器来解析上传数据,解析结果返回的是一个List<FileItem>
40             //集合,每一个FileItem对应一个Form表单的输入项
41             List<FileItem> list = upload.parseRequest(req);
42             for(FileItem item:list) {
43                 if (item.isFormField()) {
44                     String name = item.getFieldName();
45                     String value = item.getString("UTF-8");
46                     System.out.println(name + "=" + value);
47                 } else {
48                     String filename = item.getName();
49                     System.out.println(filename);
50                     if (filename == null || filename.trim().equals("")) {
51                         continue;
52                     }
53                     //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
54                     //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
55                     filename = filename.substring(filename.lastIndexOf("\\") + 1);
56                     //获取item输入流
57                     InputStream inputStream = item.getInputStream();
58                     //创建一个文件输出流
59                     FileOutputStream fileOutputStream  =new FileOutputStream(savePath+"\\"+filename);
60                     //创建一个缓冲区
61                     byte buffer[] = new byte[1024];
62                     //判断输入流是否已经读完的标识
63                     int len = 0;
64                     while ((len=inputStream.read(buffer))>0)
65                     {
66                         fileOutputStream.write(buffer,0,len);
67                     }
68                     inputStream.close();
69                     fileOutputStream.close();
70                     item.delete();
71                     message = "文件上传成功";
72
73
74
75                 }
76             }
77         }catch (Exception e)
78         {
79             message = "文件上传失败";
80             e.printStackTrace();
81         }
82         req.setAttribute("message",message);
83         req.getRequestDispatcher("/message.jsp").forward(req,resp);
84     }
85
86     @Override
87     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
88         doGet(req,resp);
89     }
90 }

改进实现:

package com.qq.upload;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
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 java.io.*;
import java.util.List;
import java.util.UUID;

/**         上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的
          1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
          2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
          3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。
          4、要限制上传文件的最大值。
          5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。*/
@WebServlet("/doUpload2")
public class Upload2  extends HttpServlet {

    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //得到上传文件的保存目录,将上传的文件存放在WEB-INF目录下面 不允许外界直接访问,保证上传文件的安全
        String savePath = this.getServletContext().getRealPath("/LoadJsp");
        String tempPath = this.getServletContext().getRealPath("/LoadJsp/temp");
        File file  =new File(tempPath);
        if(!file.exists()&&!file.isDirectory()){
            System.out.println(tempPath+"目标目录不存在,需要进行创建");
            file.mkdir();

        }
        String message = null;
        try {
            //1 创建DiskFileItemFactory工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //设置缓冲区得大小
            factory.setSizeThreshold(1024*1000000);
            //设置上传时生成得临时文件保存目录
            factory.setRepository(file);
            //2 创建一个文件上传解析器
            ServletFileUpload upload = new ServletFileUpload(factory);
            //监听文件上传速度
            upload.setProgressListener(new ProgressListener() {
                @Override
                public void update(long pBytesRead, long pContentLength, int arg2) {
                    System.out.println("文件大小为:" + pContentLength+"当前处理"+pBytesRead);
                }
            });
            //判断提交上来的数据是不是表单上的数据
            upload.setHeaderEncoding("UTF-8");
            if (!ServletFileUpload.isMultipartContent(req)) {
                return;
            }
            //设置上传文件总量得最大值
            upload.setSizeMax(1024*10*1024000);
            //设置单个上传文件得最大值
            upload.setFileSizeMax(1024*1000000);

            //4 使用ServletFileUpload解析器来解析上传数据,解析结果返回的是一个List<FileItem>
            //集合,每一个FileItem对应一个Form表单的输入项
            List<FileItem> list = upload.parseRequest(req);
            for(FileItem item:list) {
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    String value = item.getString("UTF-8");
                    System.out.println(name + "=" + value);
                } else {
                    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    fileExname = filename.substring(filename.lastIndexOf(".")+1);
                    System.out.println("上传的文件的扩展名是:"+fileExname);
                    //获取item输入流
                    InputStream inputStream = item.getInputStream();
                    //得到保存文件得名称
                    String saveFilename  = makeFileName(filename);
                    //得到文件得保存目录
                    String realSavaPath = makePath(saveFilename,savePath);
                    //创建一个文件输出流

                    FileOutputStream fileOutputStream  =new FileOutputStream(realSavaPath
                            +"\\"+saveFilename);
                    //创建一个缓冲区
                    byte buffer[] = new byte[1024];
                    //判断输入流是否已经读完的标识
                    int len = 0;
                    while ((len=inputStream.read(buffer))>0)
                    {
                        fileOutputStream.write(buffer,0,len);
                    }
                    inputStream.close();
                    fileOutputStream.close();
                   // item.delete();
                    message = "文件上传成功";

                }
            }
        }catch (Exception e)
        {
            message = "文件上传失败";
            e.printStackTrace();
        }
        req.setAttribute("message",message);
        req.getRequestDispatcher("/message.jsp").forward(req,resp);
    }

    /**
     * @method:makeFileName
     * 生成上传文件的文件名,文件名以:UUID标识符+"_"+文件的原始名称
     * @param filename
     * @return
     */
    private String makeFileName(String filename)
    {
        //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
        return UUID.randomUUID().toString()+"_"+filename;
    }

    /**
     * 为防止目录下面出现太多文件,要使用hash算法打算存存储
     * @param filename
     * @param savePath
     * @return
     */
    private String makePath(String filename,String savePath)
    {

        int hashcode = filename.hashCode();
        int dir1 = hashcode&0xf;//0--15
        /*int dir2 = (hashcode&0xf0)>>4;//0--15*/

        //构建新的保存目录
        String dir   = savePath+"\\"+dir1;
        //File可以代表文件也可以代表目录
        File file = new File(dir);
        if(!file.exists())
        {
            file.mkdir();
            System.out.println("创建新目录成功!路径地址为:"+dir);

        }
        return  dir;

    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
列出WEB系统中所有下载文件:
package com.qq.upload;

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 java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @BelongsPackage: com.qq.upload
 * @Author: ZHENGZHIQIANG
 * @CreateTime: 2019-03-18 11:16
 * @Description: 列出WEB系统中所有下载文件
 */
@WebServlet("/ListFileServlet")
public class ListFileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取上传文件的目录
        String uploadFilePath = this.getServletContext().getRealPath("/LoadJsp");
        //存储要下载的文件名
        Map<String, String> fileNameMap = new HashMap<>();
        //遍历filepath目录下面的所有文件和目录,将文件的文件名称存储到map中
        listfile(new File(uploadFilePath), fileNameMap);
        //将Map集合发送到listfile.jsp页面进行显示
        req.setAttribute("fileNameMap", fileNameMap);
        req.getRequestDispatcher("/listfile.jsp").forward(req, resp);
    }

    public void listfile(File file, Map<String, String> map) {
        if (!file.exists()) {
            File files[] = file.listFiles();
            //遍历files数组
            for (File f : files) {
                listfile(f, map);
            }
        } else {
            /*
             处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
             file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi
             那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分
             */
            String realName = file.getName().substring(file.getName().indexOf("_") + 1);
            //file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复
            map.put(file.getName(), realName);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

实现文件下载功能:
package com.qq.upload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @Description: 实现文件下载功能
 * @Author: ZHENGZHIQIANG
 * @CreateTime: 2019-03-21 10:43
 */
public class DownLoadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //得到要下载的文件名称
        String fileName =  req.getParameter("filename");
        fileName = new String(fileName.getBytes("iso8859-1"),"utf-8");
        //上传文件都是保存在/web-inf/loadjsp目录下的子目录中
        String fileSaveRootPath = this.getServletContext().getRealPath("/LoadJsp");
        //通过文件名找到文件所在的目录
        String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
        //得到要下载的文件
        File file = new File(path+"\\"+fileName);
        if(!file.exists())
        {
            req.setAttribute("message","您要下载的资源不存在");
            req.getRequestDispatcher("/message.jsp").forward(req,resp);
            return;
        }
        //处理文件名称
        String realName = fileName.substring(fileName.lastIndexOf("_")+1);
        //控制浏览器下载该文件
        resp.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(realName,"UTF-8"));
        //读取需要下载的文件 保存到文件输入流
        FileInputStream fileInputStream = new FileInputStream(path+"//"+fileName);
        //创建输出流
        OutputStream fileOutputStream = resp.getOutputStream();
        //创建缓冲区
        byte []buffer =new byte[1024];
        int len =0;
        while ((len = fileInputStream.read(buffer))>0)
        {
            fileOutputStream.write(buffer,0,len);
        }
        fileInputStream.close();
        fileOutputStream.close();
    }
        public String findFileSavePathByFileName(String filename,String saveRootPath)
        {
            int hashcode = filename.hashCode();
            int dir1 = hashcode&0xf;
            String dir  = saveRootPath+"//"+dir1;
            File file = new File(dir);
            if(!file.exists())
            {
                file.mkdir();
            }
            return dir;
        }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
 

效果如下:

JSP页面代码如下:

<%--
  Created by IntelliJ IDEA.
  User: ZHENGZHIQIANG
  Date: 2019/3/11
  Time: 11:36
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>File upload</title>
  </head>
  <body>
<form action="/doUpload2" 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>

**************
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: ZHENGZHIQIANG
  Date: 2019/3/18
  Time: 11:52
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>下载文件显示页面</title>
</head>
<body>
<%--遍历Map集合--%>
<c:forEach var="me" items="${fileNameMap}">
<c:url value="/ListFileServlet" var = "downurl">
    <c:param name="filename" value="${me.key}">
    </c:param>
</c:url>
    ${me.value}<a href="${downurl}">下载</a>
    <br/>
</c:forEach>

</body>
</html>
********************
<%--
  Created by IntelliJ IDEA.
  User: ZHENGZHIQIANG
  Date: 2019/3/13
  Time: 16:28
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Return message</title>
</head>
<body>
${message}
</body>
</html>

原文地址:https://www.cnblogs.com/zqoceean/p/10583262.html

时间: 2024-07-29 21:30:32

JavaWeb(六) IO流实现文件上传下载的相关文章

JavaWeb实现文件上传下载功能实例解析

转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件

JavaWeb实现文件上传下载功能实例解析 (好用)

转: 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上

JavaWeb 文件上传下载

1. 文件上传下载概述 1.1. 什么是文件上传下载 所谓文件上传下载就是将本地文件上传到服务器端,从服务器端下载文件到本地的过程.例如目前网站需要上传头像.上传下载图片或网盘等功能都是利用文件上传下载功能实现的. 文件上传下载实际上是两步操作,第一是文件上传,就是将本地文件上传到服务器端,实现文件多用户之间的共享,第二是文件下载,就是将服务器端的文件下载到本地磁盘. 1.2. 文件上传下载实现原理 首先,需要知道文件是如何实现上传及下载的.文件上传及下载实现原理如下: 文件上传实现流程如下:

国际化、文件上传下载

原生实现,步骤优点复杂: 国际化: 根据Local代表的区域信息可以进行国际化(了解) 1.得到你要国际化的区域信息,local cn = Local.CHINA; 2.需要使用ResourceBundle绑定写好的国际化资源文件,(基础名_语言代码_国家代码.properties) ResourceBundle bundle = ResourceBundle.getBundle("bookstore",cn); 3.从bundle中获取配置文件中的值 String username

java web 文件上传下载

文件上传下载案例: 首先是此案例工程的目录结构: 处理上传: FileUploadServlet.java 1 package fnz.fileUploadTest; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.PrintWriter; 7 import java.text.SimpleDateFormat; 8 import java.

艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输)(一)

艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开元,作者是英国的,开发时间5年多,框架很稳定. 项目地址:http://www.51aspx.com/code/MSDCArtMengFileUpload 咨询qq:286275658 演示程序下载地址:http://pan.baidu.com/s/1geVfmcr 服务器端运行效果图: 服务器端配置文件: <?xml version="1.

.Net Core 图片文件上传下载

当下.Net Core项目可是如雨后春笋一般发展起来,作为.Net大军中的一员,我热忱地拥抱了.Net Core并且积极使用其进行业务的开发,我们先介绍下.Net Core项目下实现文件上传下载接口. 一.开发环境 毋庸置疑,宇宙第一IDE VisualStudio 2017 二.项目结构 FilesController 文件上传下载控制器 PictureController 图片上传下载控制器 Return_Helper_DG 返回值帮助类 三.关键代码 1.首先我们来看Startup.cs

ssh框架文件上传下载

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="Author" content="BuNuo"> <meta name="Keywords" content="文件上传下载"> <meta name="

SpringMVC文件上传下载

在Spring MVC的基础框架搭建起来后,我们测试了spring mvc中的返回值类型,如果你还没有搭建好springmvc的架构请参考博文->http://www.cnblogs.com/qixiaoyizhan/p/5819392.html 今天我们来讲讲spring mvc中的文件上传和下载的几种方法. 首先附上文件目录->我们需要配置的我做了记号-> 一.文件上传 首先为了方便后续的操作,以及精简代码,我们在Utils包下封装一个文件上传下载的帮助类: Files_Helper