文件上传下载

文件上传实现

上传表单要求

文件上传要求客户端表单提交特殊的请求—multipart请求,即包含多部分数据的请求。所以文件上传表单对于表单数据编码类型要求,必须为multipart/form-data.即要在form标签中指定enctype属性值为“multipart/form-data”.enctype即encoding Type,编码类型。

由于客户端上传文件大小是不确定的,所以HTTP协议规定,文件上传的数据要存放在请求正文中,而不能出现在URL地址栏中,因为地址栏可以存放的数据量太小,文件上传 表单,必须提交POST请求,而不能提交GET请求。

案例:

本案例只介绍multipart请求格式是怎样的,由于本案例中使用的是Maven工程所以需要导入依赖,来支持HttpServlet

pom.xml文件:
<!-- 引入servlet-api和jsp-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
      <scope>provided</scope>
    </dependency>
前端页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>文件上传案例</title>
</head>
<body>
    <%--文件上传对表单的要求:
    1、表单中的请求类型必须为POST
    2、enctype="multipart/form-data"
    --%>
    <form action="${pageContext.request.contextPath}/upload" method="POST" enctype="multipart/form-data">
       图片: <input type="file" name="photo"/><br>
        <input type="submit" value="上传"/>
    </form>
</body>
</html>
后端代码:
@WebServlet("/upload")
public class upload extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("表单提交");
    }
}
请求结果:

在这里插入图片描述

multipart请求中可以看到上传的文件名和上传文件类型以及上传文件内容

文件上传案例

项目目录:

在这里插入图片描述

pom.xml文件
导入的依赖:
<!--文件上传解析依赖-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>

当运行程序的时候上传文件会报目标路径找步到错误。这是由于编译打包的时候没有把目标文件编译进去的

在<plugins>节点添加
 <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.2</version>
        <configuration>
          <includeEmptyDirectories>true</includeEmptyDirectories>
        </configuration>
      </plugin>
后端接口
@WebServlet("/upload")
public class upload extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        /**判断是否是multipart请求
         * */
        if(ServletFileUpload.isMultipartContent(req)){
            /**创建一个fileItem工厂
             * */
            DiskFileItemFactory diskFileItemFactory=new DiskFileItemFactory();
            /**创建文件核心组件
             * */
            ServletFileUpload upload=new ServletFileUpload(diskFileItemFactory);
            try {/**解析请求
                    * */
                List<FileItem> items=upload.parseRequest(req);
                /**遍历Items
                 * */
                for (FileItem item: items) {
                    /**判断请求中是否为普遍表单项
                     * 即请求中除了上传文件意外的参数
                     * */
                    if(item.isFormField()){
                        /**获取表单项名称
                         * */
                        String fileName=item.getFieldName();
                        String fileValue=item.getString();
                        System.out.println(fileName+"  "+fileValue);
                    }else{
                        /**代码执行到这说明上传的是文件
                         * */
                        /**获取上传文件名
                         * */
                        String fileName=item.getName();
                        InputStream is=item.getInputStream();
                        /**文件保存到服务器的路径
                         * */
                        String path=this.getServletContext().getRealPath("/UploadFile");
                        System.out.println(path);
                        File file=new File(path,fileName);
                        OutputStream os=new FileOutputStream(file);
                        /**将输入流中的数据写入到输出流中
                         * */
                        int len=-1;
                        byte[] buffer=new byte[1024];
                        while ((len=is.read(buffer))!=-1){
                            os.write(buffer,0,len);
                        }
                        /**关闭流
                         * */
                        os.close();
                        is.close();
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
        }
    }
}

本案例中上传到服务器的UploadFile文件夹中是因为程序没有对本地磁盘有写的权限

前端页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>文件上传案例</title>
</head>
<body>
    <%--文件上传对表单的要求:
    1、表单中的请求类型必须为POST
    2、enctype="multipart/form-data"
    --%>
    <form action="${pageContext.request.contextPath}/upload" method="POST" enctype="multipart/form-data">
       图片: <input type="file" name="photo"/><br>
        <input type="submit" value="上传"/>
    </form>
</body>
</html>

注意:由于上传的是服务器的指定文件夹,所以在当前项目中不会有上传的文件,本案例中在E:\TangJiachang\Tomcat\apache-tomcat-9.0.33\webapps\webTest_war\UploadFile即可找到上传的文件(从path变量中可以查看)

临时文件的使用

由于文件的传输过程做会把文件切割为一小段一小端的文件块,当上传服务器的时候这些一小端的文件块可能会从不同的网络节点传输过来,由于不同网络节点的网络拥堵情况不同就会导致文件块抵达服务器的情况不同,所以使用临时文件来将不同抵达服务器的文件块组合起来。

后端代码:
/**创建一个fileItem工厂
             * */
            DiskFileItemFactory diskFileItemFactory=new DiskFileItemFactory();
            /**设置临时文件的边界值,当上传文件大于这个值的时候
             * 就将上传的文件保存到这个临时文件中其临时文件保存在磁盘中,
             * 否则将临时文件保存到磁盘中
             * 单位为字节
             * */
            diskFileItemFactory.setSizeThreshold(1024);
            /**设置临时文件
             * */
            String tempPath=this.getServletContext().getRealPath("/temp");
            System.out.println(tempPath);
            File temp=new File(tempPath);
            diskFileItemFactory.setRepository(temp);
            /**创建文件核心组件
             * */
            ServletFileUpload upload=new ServletFileUpload(diskFileItemFactory);
删除临时文件
/**关闭流
                         * */
                        os.close();
                        is.close();
                        /**删除临时文件
                         * */
                        item.delete();

注意:当使用Maven工程的时候每次在webapp下创建新的文件夹都需要打包编译。如图:

在这里插入图片描述

文件上传带普通表单项中文乱码问题
/**获取表单项名称
                         * */
                        String fileName=item.getFieldName();
                        String fileValue=item.getString("utf-8");
                        System.out.println(fileName+"  "+fileValue);

在获取属性值的时候设置编码方式即可,也可以在item中设置

upload.setHeaderEncoding("utf-8");
限制上传文件大小
/**上传单个文件的最大边界值
 * 单位为字节
 * */
upload.setFileSizeMax(1024*1024*1);
/**设置一次上传所有文件的总和的最大值边界
 * 只对多个文件上传有效
 * */
upload.setSizeMax(1024*1024*1);

文件下载

当使用超链接的时候会由于浏览器可以将一些文件解析的时候浏览器就会解析不会下载。

案例:
项目目录:

在这里插入图片描述

注意:下载是将服务器中的资源下载到客户端,所以资源文件是保存在webapp的resources(也可以其他文件名)中。

前端页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>文件下载传案例</title>
</head>
<body>
    <a href="${pageContext.request.contextPath}/download">test.txt</a>
</body>
</html>
后端代码
@WebServlet("/download")
public class download extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /**修改响应的头部属性content-disposition值为attachment
         * 即可防止浏览器可以解析的一些文件直接让浏览器解析而不下载
         * */
        /**由于浏览器只识别ISO8859-1的字符编码所以
         * 需要设置目标字符编码
         * */
        String downfilename="中文乱码测试.txt";
        /**打散是将原来的字符编码打撒
         * */
        byte[] bytes=downfilename.getBytes("utf-8");
        /**组装是按目标字符编码组装
         * */
        downfilename=new String(bytes,"ISO8859-1");
        resp.setHeader("content-disposition","attachment;filename="+downfilename);
        /**连接服务器中的资源输入流
         * */
        InputStream is= this.getServletContext().getResourceAsStream("resources/test.txt");
        /**获取输出流
         * */
        ServletOutputStream os= resp.getOutputStream();
        int len=-1;
        byte[] buffer=new byte[1024];
        while((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
        os.close();
        is.close();
    }
}

由于本案例中使用的是Maven工程,所以需要将webapp目录下的文件夹编译到war包中

 <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.2</version>
        <configuration>
          <includeEmptyDirectories>true</includeEmptyDirectories>
        </configuration>
      </plugin>

将以上代码添加到<plugins>

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页