文件上传和下载

文件上传

1.文件上传的原理:

要实现Web开发中的文件上传功能,通常需完成两步操作:一是Web项目的页面中添加上传输入项,二是Servlet中读取上传文件的数据,并保存到目标路径中

由于大多数文件的上传都是通过表单的形式提交给服务器的,因此,要想在程序中实现文件上传功能,首先要创建一个用于提交上传文件的表单页面。在表单页面中,需要使用<input type="file">标签jsp页面中添加文件上传输入项。

<input type="file">标签

<input type="file">标签的使用需要注意以下两点:

a. 必须要设置 input 输入项的 name 属性,否则浏览器将不会发送上传文件的数据。
b. 必须把将表单页面的 method 属性设置为 post 方式, enctype 属性设置为“ multipart/form-data ”类型。

为了方便处理用户上传的数据,Apache组织提供了一个开源组件Commons- FileUpload,该组件可以方便地将multipart/form-data”类型请求中的各种表单域解析出来,并实现一个或多个文件的上传,同时也可以限制上传文件的大小等。Commons-FileUpload组件性能十分优异,并且使用非常简单。

2.Commons- FileUpload组件的工作流程:

2.1 FileItem接口

        FileItem接口主要用于封装单个表单字段元素的数据,一个表单字段元素对应一个FileItem对象。Commons-FileUpload组件在处理文件上传的过程中,将每一个表单域(包括普通的文本表单域和文件域)封装在一个FileItem对象中。

2.2 DiskFileItemFactory

        DiskFileItemFactory类用于将请求消息实体中的每一个文件封装成单独的FileItem对象。如果上传的文件比较小,将直接保存在内存中,如果上传的文件比较大,则会以临时文件的形式,保存在磁盘的临时文件夹中。默认情况下,不管文件保存在内存还是磁盘临时文件夹,文件存储的临界值是10240字节,即10KB

方法声明

功能描述

DiskFileItemFactory()

采用默认临界值和系统临时文件夹构造文件项工厂对象

DiskFileItemFactory(int sizeThresholdFile repository)

采用参数指定临界值和系统临时文件夹构造文件项工厂对象

列举了DiskFileItemFactory类的两个构造方法,其中,第二个构造方法需要传递两个参数,第一个参数sizeThreshold表示文件保存在内存还是磁盘临时文件夹中的临界值,第二个参数repository表示临时文件的存储路径。

2.3 ServletFileUpload

ServletFileUpload类是Apache组件处理文件上传的核心高级类,通过调用parseRequest(HttpServletRequest) 方法可以将HTML中每个表单提交的数据封装成一个FileItem对象,然后以List列表的形式返回。

方法声明

功能描述

ServletFileUpload()

构造一个未初始化的ServletFileUpload实例对象

ServletFileUpload(FileItemFactory fileItemFactory)

根据参数指定的FileItemFactory 对象创建一个ServletFileUpload对象

列举了ServletFileUpload类的两个构造方法。在文件上传过程中,在使用第一个构造方法创建ServletFileUpload对象时,需要在解析请求之前调用setFileItemFactory()方法设置fileItemFactory属性。

3.动手实践:实现文件上传

3.1 测试页面:

<form action="/UploadServlet" method="post" enctype="multipart/form-data">

    <table width="600px">

      <tr>
        <td>上传者:</td>
        <td><input type="text" name="myText"></td>
      </tr>

      <tr>
        <td>上传文件:</td>
        <td><input type="file" name="myFile"></td>
      </tr>

      <tr>
        <td colspan="2"><input type="submit" value="上传"></td>
      </tr>
    </table>
  </form>

3.2 UploadServlet代码:

package com.yy.controller;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
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.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;


@WebServlet(name = "UploadServlet",urlPatterns = "/UploadServlet")
public class UploadServlet extends HttpServlet {


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            //防止浏览器打印中文,出现乱码问题
            resp.setContentType("text/html;charset=utf-8");
            //创建DiskFileItemFactory的对象    用于作为创建ServletFileUpload对象的参数
            DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
            //创建ServletFileUpload的对象
            ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);


            File f = new File("C:\\Users\\Administrator\\Desktop\\temp\\");

            if (!f.exists()) {
                f.mkdirs();
            }
            fileItemFactory.setRepository(f);


            //设置编码格式
            fileUpload.setHeaderEncoding("utf-8");
            //解析req 对象  得到FileItem的集合
            List<FileItem> fileItems = fileUpload.parseRequest(req);

            //遍历fileItems集合  拿到每一个fileItem对象
            for (FileItem fileItem : fileItems) {
                //判断是否为普通字段
                if (fileItem.isFormField()) {
                    //通过获取fileItem中的name属性值  与   前端的name属性值做对比
                    if (fileItem.getFieldName().equals("myText")) {
                        //获取name属性为myText  的控件输入的普通文本内容
                        String value = fileItem.getString("utf-8");
                        //浏览器打印
                        resp.getWriter().print("上传者:" + value + "<br/>");
                    }
                } else if (fileItem.getFieldName().equals("myFile")) {
                    //获取上传的文件名
                    String filename = fileItem.getName();//study.PNG
                    if (filename != null && !filename.equals("")) {
                        //浏览器打印
                        resp.getWriter().print("上传的文件名:" + filename + "<br/>");
                        //保证文件名不重复   即保证上传的文件名字唯一
                        filename = UUID.randomUUID().toString().substring(0, 8) + "_" + filename; //uuid_study.PNG


                        //上传到服务器的发布路径
//                        String wenPath = "/upload/";
//                        String uploadPath = getServletContext().getRealPath(wenPath + filename);

                        //上传路径
                        String uploadPath = "C:\\Users\\Administrator\\Desktop\\photo\\" + filename;

                        //创建文件
                        File file = new File(uploadPath);
                        file.getParentFile().mkdirs();
                        file.createNewFile();
                        //获取上传文件流
                        InputStream in = fileItem.getInputStream();
                        FileOutputStream out = new FileOutputStream(file);
                        byte[] bytes = new byte[1024];
                        int len;
                        while ((len = in.read(bytes)) > 0) {
                            out.write(bytes, 0, len);
                        }
                        //关闭资源
                        in.close();
                        out.close();
                        //删除临时文件
                        fileItem.delete();
                        resp.getWriter().print("文件上传成功!");
                    }

                }

            }


        } catch (FileUploadException e) {
            e.printStackTrace();
        }


    }
}

 需要注意的是,untitled2项目的out \artifacts\untitled2\upload目录是IDEA默认发布的路径目录,如果读者将项目发布目录配置在Tomcatwebapps中,可以去webapps中的untitled2项目中查看。

文件下载

2.1文件下载的过程

        浏览器通常会直接处理响应的实体内容,需要在HTTP响应消息中设置两个响应消息头字段,用来指定接收程序处理数据内容的方式为下载。当单击“下载”超链接时,系统将请求提交到对应的Servlet。在Servlet中,首先获取下载文件的地址,并根据文件下载地址创建文件字节输入流,然后通过输入流读取要下载的文件内容,最后将读取的内容通过输出流写到目标文件中。

package com.yy.controller;
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet(name = "DownloadServlet",urlPatterns = "/DownloadServlet")
public class DownloadServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置ContentType字段值
        response.setContentType("text/html;charset=utf-8");
        //获取所要下载的文件名称
        String filename = request.getParameter("filename");
        //下载文件所在目录
        String folder = "/download/";
        // 通知浏览器以下载的方式打开
        response.addHeader("Content-Type", "application/octet-stream");
        response.addHeader("Content-Disposition",
                "attachment;filename="+filename);
        folder=folder+filename;
        // 通过文件流读取文件
        InputStream in = getServletContext().getResourceAsStream(folder);
        // 获取response对象的输出流
        OutputStream out = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        //循环取出流中的数据
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
    }
}

 在untitled2项目的web目录下创建一个名称为download的文件夹,在该文件夹中放置一个名称为“1.png”的图片文件。

<body>
  <a href=
    "http://localhost:8080/untitled2/DownloadServlet?filename=1.png">
      文件下载</a>
</body>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/229002.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

北邮22级信通院数电:Verilog-FPGA(12)第十二周实验(2)彩虹呼吸灯(bug已解决 更新至3.0)

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 一.代码部分 1.1一些更新和讲解 1.2改正后的…

【网络编程】-- 02 端口、通信协议

网络编程 3 端口 端口表示计算机上的一个程序的进程 不同的进程有不同的端口号&#xff01;用来区分不同的软件进程 被规定总共0~65535 TCP,UDP&#xff1a;65535 * 2 在同一协议下&#xff0c;端口号不可以冲突占用 端口分类&#xff1a; 公有端口&#xff1a;0~1023 HT…

Linux环境下用yum安装postgres15

1. 下载PostgreSQL 15 安装包 在官网选择对应版本的安装包 https://www.postgresql.org/download/ Linux | CentOS 7 | PostgreSQL 15 2. 安装PostgreSQL 15 sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-la…

chrome安装jsonview

写在前面 通过jsonview可以实现&#xff0c;当http响应时application/json时直接在浏览器格式化显示&#xff0c;增加可读性。本文看下如何安装该插件到chrome中。 1&#xff1a;安装 首先在这里 下载插件包&#xff0c;然后解压备用。接着在chrome按照如下步骤操作&#xf…

小程序一键生成工具哪个好?

在这个数字化时代&#xff0c;小程序已经成为商家吸引客户、提升业务的重要工具。但是&#xff0c;传统的小程序开发方式既费时又费力&#xff0c;让许多商家望而却步。 现在&#xff0c;有了乔拓云小程序模板开发平台&#xff0c;一切都变了。 乔拓云提供了大量精心设计的模板…

销售技巧培训之如何提高手机销售技巧

销售技巧培训之如何提高手机销售技巧 随着科技的迅速发展&#xff0c;手机已成为我们日常生活中不可或缺的一部分。作为一名手机销售员&#xff0c;了解手机销售技巧是必不可少的。本文将通过案例分析与实践&#xff0c;为你揭示手机销售的奥秘。 一、了解客户需求 在销售过程…

自动化运维工具-ansible部署

首先我们来谈一下&#xff0c;为什么要引入自动化运维呢&#xff1f; 引入自动化运维的目的是为了提高运维效率、降低人工操作的错误率、减少重复性的工作、提高系统的可靠性和稳定性。传统的手动运维方式存在以下问题&#xff1a; 出现了大量的人工干预&#xff0c;运维人员需…

Web端在线云剪辑方案

视频内容已经成为企业传播信息、展示品牌形象的重要手段。然而&#xff0c;视频制作并非易事&#xff0c;需要专业的技术和设备支持。为了帮助企业解决这个问题&#xff0c;美摄科技推出了Web端在线云剪辑方案&#xff0c;提供广播级专业技术赋能&#xff0c;帮助企业快速搭建视…

最新V2board面板支付设置(四)

顺哥博客 支付方式一&#xff08;推荐&#xff09;&#xff1a; USDT收款&#xff1a; 特点&#xff1a;自己的USDT钱包收款&#xff0c;没有中间商&#xff0c;无手续费&#xff0c;实时到账项目开源地址&#xff1a;【点击进入】把文件usdtwebhook.php放到网站此目录下&…

使用命令行移除VSAN中故障磁盘

原创作者&#xff1a;运维工程师 谢晋 使用命令行移除VSAN中故障磁盘 前提故障盘移除 前提 客户有套VSAN环境内有一台服务器的磁盘组出现了一块故障的数据盘&#xff0c;但该盘已经处于完全掉线状态&#xff0c;无法进行正常移除。如下图&#xff1a; 如果遇到这种情况&am…

QT作业2

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…

为什么Java程序员需要掌握多线程?揭秘并发编程的奥秘

为什么Java程序员需要掌握多线程&#xff1f;揭秘并发编程的奥秘 个人简介前言多线程对于Java的意义&#x1f4cc;1.提高程序性能&#xff1a;&#x1f4cc;2 提高用户体验&#xff1a;&#x1f4cc;3支持并发处理&#xff1a;&#x1f4cc;4 资源共享和同步&#xff1a;&#…

el-tree数据量过大,造成浏览器卡死、崩溃

el-tree数据量过大&#xff0c;造成浏览器卡死、崩溃 场景&#xff1a;树形结构展示&#xff0c;数据超级多&#xff0c;超过万条&#xff0c;每次打开都会崩溃 我这里采用的是引入新的插件虚拟树&#xff0c;它是参照element-plus 中TreeV2改造vue2.x版本虚拟化树形控件&…

Navicat 技术指引 | 适用于 GaussDB 分布式的数据迁移工具

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

选自《洛谷深入浅出进阶篇》——欧拉函数+欧拉定理+扩展欧拉定理

欧拉函数&#xff1a; 欧拉函数定义&#xff1a; 1~n中与n互质的数的个数。 比如 欧拉函数是积性函数&#xff1a;&#xff08;也就是&#xff09;当 n与m互质的时候&#xff1a; 由算术基本定理&#xff0c;我们可以设n&#xff0c;那么我们只要计算出的取值就能求出的取…

snakeyaml编辑yaml文件并覆盖注释

文章目录 前言技术积累实战演示1、引入maven依赖2、覆盖注释工具类3、snakeyaml工具类4、测试用例5、测试效果展示 写在最后 前言 最近在做一个动态整合框架的项目&#xff0c;需要根据需求动态组装各个功能模块。其中就涉及到了在application.yaml中加入其他模块的配置&#…

Windows版Minio使用教程(启动,登录,修改密码)

1 、下载安装包 进入官网下载安装包&#xff1a; MinIO | 高性能、支持原生 Kubernetes的对象存储 信任程序安装&#xff0c;就可以啦 2、启动MinIO 第一步&#xff0c;找到minio.exe所在的目录&#xff0c;在地址栏输入cmd进入cmd窗口。 第二步&#xff0c;输入.\minio.exe…

项目状态报告

《项目状态报告》 第1章 当前阶段的工作完成情况 1.1 概述 1.2 各子系统详细进度 第2章 偏差及偏差原因 第3章 偏差纠正措施 第4章 拟进行的变更 第5章 存在的风险及应对计划 第6章 下一阶段主要工作

delphi android打开外部文件,报错android.os.FileUriExposedException解决方法

Android 7.0强制启用了被称作 StrictMode的策略&#xff0c;带来的影响就是你的App对外无法暴露file://类型的URI了。 如果你使用Intent携带这样的URI去打开外部App(比如&#xff1a;打开系统相机拍照)&#xff0c;那么会抛出FileUriExposedException异常。 Delphi 为Android…

Python源码30:海龟画图turtle画紫色的小熊

turtle模块是一个Python的标准库之一&#xff0c;它提供了一个基于Turtle graphics的绘图库。Turtle graphics是一种流行的绘图方式&#xff0c;它通过控制一个小海龟在屏幕上移动来绘制图形。 turtle模块可以让您轻松地创建和控制海龟图形&#xff0c;从而帮助您学习Python编…