先导入jar包

  点击下载

  commons-fileupload是Apache开发的一款专门用来处理上传的工具,它的作用就是可以从request对象中解析出,用户发送的请求参数和上传文件的流。

  commons-fileupload包依赖commons-io,两个包需要同时导入。

  tomcat内置的jar包只能在tomcat服务器使用。

上传文件的方法

  1、创建DiskFileItemFactory工厂类的实例

    DiskFileItemFactory dfif=new DiskFileItemFactory();//new 一个DiskFileItemFactory对象

    DiskFileItemFactory类介绍

       工厂类,用于创建ServletFileUpload,设置缓存等

       该类一般直接使用构造器直接创建实例

       方法:

         public void setSizeThreshold(int sizeThreshold)

           用于设置缓存文件的大小(默认值10kb)

         public void setRepository(File repository)

           用于设置缓存文件位置(默认系统缓存目录)

  2、获取ServletFileUpload解析器的实例

    ServletFileUpload sfu=new ServletFileUpload(dfif);//通过DiskFileItemFactory对象获取ServletFileUpload解析器实例

    ServletFileUpload类介绍

       该类用于解析request对象从而获取用户发送的请求参数(包括普通参数和文件参数)

       该类需要调用有参构造器创建实例,构造器中需要一个DiskFileItemFactory作为参数

       方法:

        public List<FileItem> parseRequest(HttpServletRequest request)

           解析request对象,获取请求参数,返回的是一个List,List中保存的是一个FileItem对象,一个对象代表一个请求参数。

         public void setFileSizeMax(long fileSizeMax)

          设置单个文件的大小限制,单位为B 如果上传文件超出限制,会在parseRequest()抛出异常FileSizeLimitExceededException。

         public void setSizeMax(long sizeMax)

          限制请求内容的总大小,单位为B 如果上传文件超出限制,会在parseRequest()抛出异常SizeLimitExceededException。

  3、获取请求参数列表

    List<FileItem> list = sfu.parseRequest(request);//用ServletFileUpload解析器对象获取参数列表,该列表包含文件参数和普通参数  

    FileItem类介绍

      该类用于封装用户发送的参数和文件,也就是用户发送来的信息将会被封装成一个FileItem对象,我们通过该对象获取请求参数或上传文件的信息。

      该类不用我们手动创建,由ServletFileItem解析request后返回。

      方法:

        String getFieldName()

          获取表单项的名字,也就是input当中的name属性的值。

        String getName();

          获取上传的文件名,普通的请求参数为null。

        String getString(String encoding);

          获取内容l 若为文件,将文件的流转换为字符串。l 若为请求参数,则获取请求参数的value。

          encoding参数需要指定一个字符集,不指定时中文会乱码,建议设置utf-8

        boolean isFormField();

          判断当前的FileItem封装的是普通请求参数,还是一个文件。如果为普通参数返回:true l 如果为文件参数返回:false

        String getContentType();

          获取上传文件的MIME类型

        long getSize();

          获取内容的大小

上传文件的例子

  jsp的代码

             <form action="${pageContext.request.contextPath }/Files"
                 method="post" enctype="multipart/form-data">
                 文件1:<input type="file" name="file1"><br>
                 <br>文件2: <input type="file" name="file2"><br>
                 <br> 文件3:<input type="file" name="file3"><br>
                 <br> 文本:<input type="text" name="text"><br>
                 <br> <input type="submit" value="上传">
             </form>    

  servlet的代码

         DiskFileItemFactory dfif = new DiskFileItemFactory();// 创建工厂类
         ServletFileUpload sfu = new ServletFileUpload(dfif);// 创建请求解析器
         sfu.setFileSizeMax(1024 * 1024 * 1);// 设置上传单个文件的的大小
         sfu.setSizeMax(1024 * 1024 * 1 * 10);// 设置上传总文件的大小
         response.setContentType("text/html;charset=utf-8");// 设置响应内容的编码
         try {
             List<FileItem> list = sfu.parseRequest(request);// 解析请求信息,获取FileItem的集合
             for (FileItem fileItem : list) {// 遍历集合
                 if (fileItem.isFormField()) {// 如果是普通的表单项
                     String fieldName = fileItem.getFieldName();// 获取参数名
                     String value = fileItem.getString("utf-8"); // 获取参数值,设置编码为utf-8防止中文乱码
                     System.out.println(fieldName + " = " + value);
                 } else {// 如果是文件表单项
                     String fileName = fileItem.getName();// 获取文件名
                     String realPath = getServletContext().getRealPath("/upload");// 获取上传路径
                     System.out.println(realPath);
                     File f = new File(realPath);// 检查upload文件夹是否存在
                     if (!f.exists()) {//如果不存在则创建
                         f.mkdir();
                     }
                     String prefix = UUID.randomUUID().toString().replace("-", "");// 为避免重名生成一个UUID作为文件名的前缀,并且将生成UUID中的-移除
                     fileItem.write(new File(realPath + "/" + prefix + "_" + fileName));// 将文件写入到服务器中
                     fileItem.delete();// 清除文件缓存
                 }
             }
         } catch (Exception e) {
             if (e instanceof SizeLimitExceededException) {
                 response.getWriter().print("上传文件的总大小不能超过10M");// 文件总大小超出限制
             } else if (e instanceof FileSizeLimitExceededException) {
                 response.getWriter().print("上传单个文件的大小不能超过1M");// 单个文件大小超出限制
             }
         }
         response.getWriter().print("上传成功");

下载文件的方法

  文件下载最直接的方法就是把文件直接放到服务器的目录中,(eclipse下可以用tc工具快速访问到tomcat的工作目录,具体看我另一片博客)用户直接访问该文件就可以直接下载。但是实际上这种方式并不一定好用,比如我们在服务器上直接放置一个MP3文件,然后通过浏览器访问该文件的地址,如果是IE浏览器可能就会弹出下载窗口,而如果是FireFox和Chrome则有可能直接播放。再有就是有一些文件我们是不希望用户可以直接访问到的,这是我们就要通过Servlet来完成下载功能。

  下载文件的几个关键点

    1、 服务器以一个流的形式将文件发送给浏览器。

    2、发送流的同时还需要设置几个响应头,来告诉浏览器下载的信息。

      具体响应头如下:

        Content-Type:下载文件的MIME类型,

               可以通过servletContext. getMimeType(String file)获取,

               也可以直接手动指定,

               使用response.setContentType(String type);

               响应头样式:Content-Type: audio/mpeg

        Content-Disposition:下载文件的名字,

                  主要作用是提供一个默认的用户名,

                  通过response.setHeader("Content-Disposition", disposition)设置

                  响应头样式:Content-Disposition: attachment; filename=xxx.mp3

         Content-Length: 下载文件的长度,用于设置文件的长处(不必须)

                 通过response. setContentLength(int len)设置。

                 设置后样式:Content-Length: 3140995

    3、 接下来需要以输入流的形式读入硬盘上的文件

        FileInputStream is = new FileInputStream(file);

        这个流就是我们一会要发送给浏览器的内容

    4、通过response获取一个输出流,并将文件(输入流)通过该流发送给浏览器

        获取输出流 ServletOutputStream out = response.getOutputStream();

        通过输出流向浏览器发送文件(不要忘了关闭输入流)

          byte[] b = new byte[1024];

          int len = 0;

          while((len=is.read(b))> 0){

            out.write(b, 0, len);

          }

          is.close();

下载的例子

  servlet代码  

         String realPath = getServletContext().getRealPath("/WEB-INF/download/风吹麦浪.mp3");// 获取文件真实地址
         File file = new File(realPath);// 获取file对象
         if (!file.exists()) {// 找不到目标文件
             response.getWriter().print("文件不存在");
             return;
         }
         FileInputStream fis = new FileInputStream(file);// 获取文件输入流
         String contentType = getServletContext().getMimeType(realPath);// 获取文件的MIME信息
         String filename = file.getName();// 设置下载文件的名字
         //设置编码格式,否则文件名为中文时会乱码
         String ua = request.getHeader("User-Agent");// 获取客户端信息
         if (ua.contains("Firefox")) {// 判断客户端是否为火狐
             filename = "=?utf-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";// 若为火狐使用BASE64编码
         } else {
             filename = URLEncoder.encode(filename, "utf-8");// 否则使用UTF-8
         }
         String disposition = "attachment; filename=" + filename;// 创建Content-Disposition信息
         long size = file.length();// 获取文件长度
         response.setContentType(contentType);// 设置Content-Type
         response.setHeader("Content-Disposition", disposition);// 设置Content-Disposition
         response.setContentLength((int) size);// 设置文件长度
         ServletOutputStream out = response.getOutputStream();// 通过response获取输出流,用于向浏览器输出内容
         byte[] buffer = new byte[1024];// 将文件输入流通过输出流输出
         int len = 0;
         while ((len = fis.read(buffer)) > 0) {
             out.write(buffer, 0, len);
         }
         fis.close();// 最后不要忘记关闭输入流,输出流由Tomcat自己处理,不用手动关闭

编码问题

    从服务器获取浏览器发送的非文件内容包含中文时,需要设置编码,如String value = fileItem.getString("utf-8"); // 获取参数值,设置编码为utf-8防止中文乱码,不设置则会乱码;

    从服务器向浏览器发送中文时,需要对内容进行URL编码。(其他编码问题请看另一篇博客,里边会记录我遇到过的编码问题)
      大部分浏览器使用如下方式即可解决乱码问题:URLEncoder.encode(fileName, "utf-8");但是火狐默认以Base64来解码的,所以要为火狐单独处理。
         可以使用如下代码来判断浏览器的类型,然后进行不同的编码处理
      就是上面例子中使用的方法

        //设置编码格式,否则文件名为中文时会乱码
         String ua = request.getHeader("User-Agent");// 获取客户端信息
         if (ua.contains("Firefox")) {// 判断客户端是否为火狐
             filename = "=?utf-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";// 若为火狐使用BASE64编码
         } else {
             filename = URLEncoder.encode(filename, "utf-8");// 否则使用UTF-8
         }

还有一种简单但还不理解的方式,亲测可用
     向将字符串用gbk进行解码,然后在使用iso8859-1进行编码
          

 filename = new String(filename.getBytes("gbk"),"iso8859-1");

SpringMVC上传文件

  Spring MVC 上下文中默认没有为文件上传提供直接的支持,因此默认情况下不能处理文件的上传工作,如果想使用 Spring 的文件上传功能,需现在上下文中配置 CommonsMultipartResovler:

  1、与上面一样同样需要导入jar包

  2、在SpringMVC配置文件中配置CommonsMultipartResovler    

         <!-- 配置CommonsMultipartResolver -->
         <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
             <property name="defaultEncoding" value="utf-8"></property>
             <!-- 以字节为单位 -->
             <property name="maxUploadSize" value="1024000"></property>
         </bean>

  3、表单:POST请求,file类型,enctype="multipart/form-data"

    表单:    

         <form action="${pageContext.request.contextPath }/fileUpload"
         method="post" enctype="multipart/form-data">
         text:<input type="text" name="text"><br> <br> 文件:<input
             type="file" name="file"><br> <br> <input
             type="submit" value="上传">
        </form>    

    controller:    

     @RequestMapping(value = "/fileUpload")
     public String fileUpload(HttpServletRequest request, @RequestParam(value = "text", required = false) String text,
             @RequestParam("file") CommonsMultipartFile file) throws Exception {

         String realPath = request.getServletContext().getRealPath("/upload");//获取真实路径
         //System.out.println(realPath);
         File file1 = new File(realPath);//创建文件夹
         if (!file1.exists()) {
             file1.mkdir();
         }
         OutputStream out = null;
         InputStream in = null;//文件输入输出流
         String prefix = UUID.randomUUID().toString();//生成唯一UUID
         String fileName = prefix + "_" + file.getOriginalFilename();
         System.out.println(fileName);
         out = new FileOutputStream(new File(realPath + "\\" + fileName));
         in = file.getInputStream();
         // IOUtils.copy(in, out);//导入的jar自带的工具类,复制文件,下面是自己写的复制方法
         int readIndex = 0;
         int copyBytes = 0;
         byte[] buffer = new byte[1024];
         while ((readIndex = in.read(buffer)) > 0) {
             out.write(buffer, 0, readIndex);
             copyBytes += readIndex;
         }
         System.out.println("共复制了:" + copyBytes + "字节");
         if (out != null)
             out.close();
         if (in != null)
             in.close();//关闭流
         return "success";
     }

SpringMVC文件下载  

     @RequestMapping(value = "/goFileDownload")//转到下载页面,将文件名显示在页面上
     public ModelAndView goFileDownload(HttpServletRequest request) throws Exception {
         ModelAndView mv = new ModelAndView();
         String path = request.getServletContext().getRealPath("/upload/");
         System.out.println(path);
         File file = new File(path);//获取目录
         File[] files = file.listFiles();
         List<String> fileName = new ArrayList<>();
         for (int i = 0; i < files.length; i++)//获取文件名list
             if (files[i].isFile())
                 fileName.add(files[i].getName());
         mv.setViewName("download");
         mv.addObject("files", fileName);
         return mv;
     }
     @RequestMapping(value = "/fileDownload/{fileName:.+}")//接受文件名参数并下载对应文件,Spring下只需将返回值设置为ResponseEntity<byte[]>即可实现
     public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,
             @PathVariable(value = "fileName") String fileName) throws Exception {
         //System.out.println(fileName);
         String path = request.getServletContext().getRealPath("/upload/" + fileName);//获取文件的真实路径
         //System.out.println(path);
         File file = new File(path);//创建文件对象,准备获取内容
         InputStream in = new FileInputStream(file);
         byte[] body = new byte[in.available()];
         in.read(body);
         if (in != null)
             in.close();
         HttpHeaders headers = new HttpHeaders();//设置响应头
         fileName = new String(fileName.getBytes("gbk"), "iso8859-1");//防止中文文件名乱码,但是我去掉也能正常下载,可能是我的文件名是接收的原因
         headers.add("Content-Disposition", "attachment;filename=" + fileName);
         HttpStatus statusCode = HttpStatus.OK;//http状态码,此时为200      参考一篇博客
         //System.out.println(statusCode);
         ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body, headers, statusCode);//设置返回值
         return response;
     }

  

  

Javaweb向服务器上传文件以及从服务器下载文件的方法的更多相关文章

  1. jQuery用FormData对象实现文件上传以及如何通过ajax下载文件

    之前在Vue的项目里面用到过文件上传,封装好的组件用起来比较顺手,查询Element-UI文档,十八般武器样样都有,一顿操作猛如虎,一看--跑偏了(⊙o⊙)-,我的意思就是用框架实现比较简单,但是如果 ...

  2. FTP服务器上传工具,FTP服务器上传工具下载!

    IIS7服务器管理工具能够作为FTP的客户端,进行FTP的命令操作,可在客户端,下载,安装FTP软件! 同时,它也可以作为VNC的客户端,进行VNC的命令操作!它能够批量连接Windows和Linux ...

  3. java使用JSCH连接FTP(Linux服务器)上传文件到Linux服务器

    首先需要用到jsch-0.1.54.jar 包: 链接: https://pan.baidu.com/s/1kZR6MqwpCYht9Pp_D6NKQw 密码: gywx 直接上代码: package ...

  4. Javaweb学习笔记——上传下载文件

    一.前言 在Javaweb中,上传下载是经常用到的功能,对于文件上传,浏览器在上传的过程中是以流的过程将文件传给服务器,一般都是使用commons-fileupload这个包实现上传功能,因为comm ...

  5. 使用批处理文件在FTP服务器 上传下载文件

    1.从ftp服务器根目录文件夹下的文件到指定的文件夹下 格式:ftp -s:[配置文件] [ftp地址] 如:ftp -s:c:\vc\ftpconfig.txt   192.168.1.1 建立一个 ...

  6. 你知道哪些linux命令,能把文件上传到远程linux服务器

    多数情况下 企业的服务基本都是部署在linux服务器 那对于测试同学,必须掌握基本的linux命令   至少要知道怎么部署整体环境   部署过程中,经常需要的操作,是向服务器上传部署包   你一般都是 ...

  7. 测试必备技能系列4:如何用SSH向linux服务器上传下载文件

    通过ssh方式,向远程服务器上传文件 非常方便 直接看老徐之前的文章http://www.51testing.com/?uid-497177-action-viewspace-itemid-37054 ...

  8. ASP.NET跨服务器上传文件的相关解决方案

    第一种:通过FTP来上传文件 首先,在另外一台服务器上设置好FTP服务,并创建好允许上传的用户和密码,然后,在ASP.NET里就可以直接将文件上传到这台 FTP 服务器上了.代码如下: <%@ ...

  9. 将本地文件上传到指定的服务器(HttpWebRequest方法)

    将本地文件上传到指定的服务器(HttpWebRequest方法),通过文件流,带文件名,同文件一同上传的表单文本域及值. ///<summary> /// 将本地文件上传到指定的服务器(H ...

  10. JavaScript进阶(九)JS实现本地文件上传至阿里云服务器

    JS实现本地文件上传至阿里云服务器 前言 在前面的博客< JavaScript进阶(八)JS实现图片预览并导入服务器功能>(点击查看详情)中,实现了JS将本地图片文件预览并上传至阿里云服务 ...

随机推荐

  1. css3-transition过渡属性

    transition主要是用于一个元素的一种状态到另一种状态的一个过渡的过程,不能够主动触发,必须依赖于事件,例如hover伪类选择器. 一,transition简写 transition:要过渡的属 ...

  2. FTP publisher plugin插件

    说明:这个插件可以将构建的产物(例如:Jar)发布到FTP中去. 官方说明:FTP publisher plugin 安装步骤: 系统管理→管理插件→可选插件→Artifact Uploaders→F ...

  3. 基于jmeter,jenkins,ANT接口,性能测试框架

    背景 公司计划推接口和性能测试,搭建这个性能测试框架框架是希望能够让每个人(开发人员.测试人员)都能快速的进行性能,接口测试,而不需要关注性能测试环境搭建过程.因为,往往配置一个性能环境可能需要很长的 ...

  4. 【科普】什么是TLS1.3

    TLS1.3是一种新的加密协议,它既能提高各地互联网用户的访问速度,又能增强安全性. 我们在访问许多网页的时候,常常会在浏览器的地址栏上看到一个锁的图标,并使用"https"代替传 ...

  5. 【grunt】grunt 基础学习

    1. 干啥的呢? 项目打包管理,用处有 1)可用于压缩合并前端文件,包括css/js , 2)可用于管理发布文件与开发文件,3)可用于自动编译less 文件 2. 常用的东西有哪些呢? 常用的插件有 ...

  6. windows下配置cygwin和dig的环境变量

    配置cygwin和dig的环境变量 打开"控制面板"("开始">"设置">"控制面板"),然后双击" ...

  7. HTMl课堂随笔

    html: 1.超文本标记语言(Hyper Text Markup Lan) 2.不是一种编程语言,而是一种标记语言(Markup Language) 3.标记语言是一套标记标签(Markup Tag ...

  8. Linux 系统下安装 rz/sz 命令及使用说明

    Linux 系统下安装 rz/sz 命令及使用说明 rz/sz命令,实现将本地的文件上传到服务器或者从服务器上下载文件到本地,但是很多Linux系统初始并没有这两个命令,以下为安装和使用的具体步骤: ...

  9. Python 文件的处理

    简单的读取文件 f.read()  是读取这个文件的所有内容 f.readline()  是读取文件的一行 .write()  会去检查这个文件是否存在,不存在则创建,存在的话,则以覆盖的方式将内容写 ...

  10. JavaScript中数组的方法总结

    js数组元素的添加和删除一直比较迷惑,今天终于找到详细说明的资料了,先给个我测试的代码^-^var arr = new Array();arr[0] = "aaa";arr[1] ...