学习笔记4:文件上传和下载

文件的上传和下载

在上网时我们会遇到很多上传下载的案例,例如图片的上传下载等。接下来我们看一下servlet怎么实现上传和下载吧。

文件的上传

文件上传涉及到前台页面和后台服务器端代码的编写,前台发送文件,后台接受并保存文件,这才是一个完整的文件上传。

前台页面:

在做文件上传时,会有一个上传文件的界面,首先需要一个表单,并且请求方式为 POST;其次,form表单的 enctype 必须设为 “multipart/form-data” ,即 enctype = “multipart/form-data”,意思是设置表单的类型为文件上传表单。默认情况下这个表单类型是 “application/x-www-from-urlencoded” ,不能用于文件上传。只有使用了 multipart/form-data 才能完整的传递数据文件。

<form action="uploadServlet" method="post" enctype="multipart/form-data">
    姓名:<input type="text" name="uname">
    文件:<input type="file" name="myfile">
    <button>提交</button>
</form>

后台实现:

使用注解 @MultipartConfig 将一个Servlet 标识为支持文件上传。Servlet 将 multipart/form-data 的POST 请求封装成Part对象,通过Part对象对上传的文件进行操作

package com.xxxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;

@WebServlet("/uploadServlet")
@MultipartConfig  //如果是文件上传,必须要加这个注解 让这个Servlet支持文件上传
public class UploadServlet extends HttpServlet {
    
    

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        System.out.println("文件上传...");

        //设置请求的编码格式
        request.setCharacterEncoding("utf-8");
        //获取普通表单项
        String uname = request.getParameter("uname");//参数为表单中表单元素的name属性值
        System.out.println("uname = " + uname);

        //获取part对象
        Part part = request.getPart("myfile");//参数为表单中file文件域的name属性值
        String fileName = part.getSubmittedFileName(); //获取提交过来的文件名
        System.out.println("filename = "+fileName);


        String filePath = request.getServletContext().getRealPath("/");//项目根目录
        System.out.println("filepath = "+filePath);
        //上传文件到指定目录(现在我们放在根目录下)
        part.write(filePath+"/"+fileName);

    }
}

servlet3.0版本以前需要使用第三方的jar包commons-fileupload来实现上传文件,servlet3.0以上版本自带了上传文件的api,无需第三方jar包
servlet3.0以上版本将上传的文件保存在Part实例中,可以通过request对象根据上传的表单控件的name获取对应的part对象,同时也支持多个文件上传
比较麻烦的地方在于文件名的获取,由于保存文件不能以上传时的文件名来保存,因为怕多人上传相同文件名而被覆盖,所以一般需要设置一个随机的不能重复的文件名,我们可以使UUID来作为文件名,至于后缀名就需要根据上传时的文件后缀来获取了,part对象里本身并没有存储上传文件的名称,我们需要从请求头信息里去获取文件名,浏览器发送上传文件请求时将文件名存储在Request Head里的Content-Disposition里,但Content-Disposition得值里除了文件名信息还有一些其他信息,所以只能通过字符串截取的方式获取文件的后缀名。

Content-Disposition:form-data; name=“file”; filename=“test.txt”

文件存储在服务器当前项目的根目录下的upload文件夹中,通过req.getServletContext().getRealPath()获取服务器的绝对再将上传的文件写入。

文件下载

文件下载就是将服务器上的资源下载到本地客户端,有两种方式,第一种是通过超链接本身的特性来下载,第二种是通过代码操作下载。
web项目大部分文件下载不需要写代码实现,只需通过超链接即可实现,就是通过超链接,在连接地址里写上文件的路径,浏览器会自动打开该文件,如果是普通的文本,图片等浏览器能直接显示内容的浏览器都能直接打开并显示,但如果是浏览器无法打开的文件,比如rar,docx,exe等等,那么浏览器就会提示你下载改文件或者使用当前系统自带的工具打开该文件

超链接下载

当我们在页面中使用a标签时,愿意时希望能够跳转,但是当超链接遇到浏览器不识别的资源时也会自动下载;
当遇见浏览器可以直接显示的资源,浏览器就会默认显示出来,比如 txt、png、jpg 等。当然,也可以通过 download 属性 规定浏览器进行下载。但有些浏览器并不支持。

<!-- 当超链接遇到不识别的资源时,会自动下载-->
<a href="test.zip">超链接下载</a>

指定 download 属性 下载:

<!--当超链接遇到浏览器识别的资源时,默认不会下载。通过download属性可进行强制下载-->
<a href="test.txt" download>超链接下载</a>

download属性可以不写任何信息,会自动使用默认文件名。如果设置了download属性的值,则使用设置的值做为文件名。当用户点击链接的时候就会直接下载。

需要注意的是,如果希望浏览器可以访问到项目里的资源,那么应该在Tomcat里进行添加外部资源的配置,如下:
在这里插入图片描述

后台实现下载

实现步骤:

  1. 需要通过response.setContentType 方法设置Content-Type 头字段的值为浏览器无法使用某种方式激活某个程序来处理的 MIME 类型,例如 “application/octet-stream” 或 “application/x-msdownload” 等。
  2. 需要通过response.setHeader 方法设置 Content-Disposition 头的值为 attachment;filename=文件名
  3. 读取下载文件,调用response.getOutputStream 方法向客户端写入附件内容。
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
    
    
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("文件下载...");
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");

        String fileName = request.getParameter("fileName");
        //判空 是否输入文件名
        if (fileName == null || "".equals(fileName.trim())){
    
    
            response.getWriter().write("请输入要下载的文件名!");
            response.getWriter().close();
            return;
        }
        //获取download文件夹的绝对路径(也就是存放项目资源的路径)
        String realPath = request.getServletContext().getRealPath("/download/");//获取download文件夹的绝对路径
        //通过路径获得这个file对象
        File file = new File(realPath+fileName);
        //判断这个文件是否存在并且是一个标准文件
        if (file.exists() && file.isFile()){
    
    
            //设置响应类型 浏览器无法使用某种方式激活某个程序来处理的 MIME 类型
            response.setContentType("application/octet-stream");
            //设置响应头
            response.setHeader("Content-Disposition","attachment;filename="+fileName);
            //得到这个文件的输入流
            InputStream in = new FileInputStream(file);
            //得到字节输出流
            ServletOutputStream out = response.getOutputStream();
            //定义byte数组
            byte[] bytes = new byte[1024];
            //定义长度
            int len = 0;
            //循环读取
            while((len = in.read(bytes)) != -1){
    
    
                out.write(bytes,0,len);
            }
            out.flush();
            out.close();
            in.close();

        }else{
    
    
            response.getWriter().write("文件不存在,请重试!");
            response.getWriter().close();
        }
    }
}

知识链接

Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。当 Internet Explorer 接收到头时,它会激活文件下载对话框,它的文件名框自动填充了头中指定的文件名。(请注意,这是设计导致的;无法使用此功能将文档保存到用户的计算机上,而不向用户询问保存位置。)

服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txt、jpg等,会直接在浏览器中显示,如果需要提示用户保存,就要利用Content-Disposition进行一下处理,关键在于一定要加上attachment:

Response.AppendHeader(“Content-Disposition”,“attachment;filename=FileName.txt”);

备注:这样浏览器会提示保存还是打开,即使选择打开,也会使用相关联的程序比如记事本打开,而不是IE直接打开了。

猜你喜欢

转载自blog.csdn.net/qq_40492885/article/details/115265405
今日推荐