Servlet文件的上传与下载详解
目录
- 文件的上传和下载
- 1. 文件上传细节
- 2. 文件上传
- 3. 文件下载
文件的上传和下载
1. 文件上传细节
要有一个 form 标签,method-post请求 (因为get有长度限制)
form标签的属性
encType
值必须为 multipart/form-data表示提交的数据以多端(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
在 form 标签中使用
input type="file"
添加上传的文件编写服务器代码 (Servlet接收),接受处理上传的数据
文件上传http请求信息:
请求头:
Content-Type: multipart/form-data;
boundary=------WebKitFormBoundaryCd3g75eOt35olUs7
解析:
Content-Type
表示提交的数据类型multipart/form-data
表示以流的形式分段提交服务器boundary
表示每段数据的分隔符,值:----WebKitFormBoundarylXiF4fEzpo9c8L4p
是浏览器每次随机生成的,它就是每段数据的分界符。在每段里面 第一行是对表单项的描述,然后有个空行,下面是提交的值。
------WebKitFormBoundaryCd3g75eOt35olUs7因为客户端是以按流的方式提交是,所以我们要按流的方式获取,不能这样:
Content-Disposition: form-data; name="username"
zhu
------WebKitFormBoundaryCd3g75eOt35olUs7
Content-Disposition: form-data; name="photo"; filename="head.jpg"
Content-Type: image/jpeg
文件的信息(很长这里省略了)
------WebKitFormBoundaryCd3g75eOt35olUs7--
req.getParameter("username");
正确用法:
@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("上传成功"); ServletInputStream inputStream = req.getInputStream(); // 先得到 字节输入流byte[] buffer = new byte[1024]; // 缓冲区int readCount = 0; while ((readCount = inputStream.read(buffer)) != -1) { // 打印出来的就是上面全部的请求体System.out.println(new String(buffer, 0, readCount)); }}
2. 文件上传
这种文件上传(常用)有很多第三方提供好的API我们使用进行了,可以帮我们对收到的数据进行解析。
例如:
commons-fileupload-1.2.1.jar
(依赖于 commons-io-1.4.jar
)- 导入两个jar包
- 解析
ServletFileUpload
类:用于解析上传的数据FileItem
类:每一个表单项
//ServletFileUpload中的方法// 判断当前上传的数据是否是多端的格式,不是解析不了public boolean ServletFileUpload.isMultipartContent(HttpServletRequest req) // 解析上传的数据,FileItem表示每一个表单项public ListparseRequest(HttpServletRequest req)//FileItem中方法// 判断当前这个表单项是普通的表单项还是文件上传的类型,true表示普通的public boolean isFormField()// 获取表单项name属性值public String getFieldName()// 获取当前表单项的值public String getString() // 可传入字符集,防止乱码,一开始req.setCharacterEncoding("UTF-8"); 也行// 获取上传的文件名public String getName()// 将上传的文件写道 参数file所指向的磁盘位置public void write(File file)
Servlet上传文件示例:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8"); // 防止乱码resp.setContentType("text/html; charset=utf-8"); String savePath = getServletContext().getRealPath("/WEB-INF/uploadFile"); //保存的路径// 首先判断上传的数据是否是多段的数据if (ServletFileUpload.isMultipartContent(req)) {FileItemFactory fileItemFactory = new DiskFileItemFactory(); // 创建FileItemFactory工厂的实现类,// 创建用于解析上传数据的工具类ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory); try {Listlist = servletFileUpload.parseRequest(req); // 解析,得到每一个表单项for (FileItem fileItem : list) {if (fileItem.isFormField()) { // 普通表单项System.out.print("表单项的name属性值:" + fileItem.getFieldName()); System.out.println("表单项的value:" + fileItem.getString("UTF-8")); } else { // 文件类型System.out.print("文件的name属性值:" + fileItem.getFieldName()); System.out.println("上传的文件名:" + fileItem.getName()); // 一般会保存到用户访问不能直接访问的目录下 File.separator是系统默认路径分隔符,win下是 / // (下面这是保存到了部署的真是目录下,保存到了服务器中)// 可以用UUID保证文件名的唯一性,防止文件覆盖。// 防止单个目录文件过多影响读写速度,还可以使用目录生成算法分散储存fileItem.write(new File(savePath + File.separator + fileItem.getName())); //fileItem.delete(); //关闭资源}}} catch (Exception e) {e.printStackTrace(); }}}
3. 文件下载
客户端 ->(发送请求告诉服务器我要下载什么文件) -> 服务器
服务器干的内容:
- 获取要下载的文件名
- 读取要下载的文件内容
- 通过响应头告诉客户端返回的数据类型是什么 (和要下载的类型一致)
- 告诉的客户端收到的数据是用于下载使用(还是用响应头设置)
- 把下载的的文件内容回传给客户端下载
commons-io-1.4.jar
的IOUtils 类:@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8"); // 防止乱码resp.setCharacterEncoding("UTF-8"); //1.获取要下载的文件名路径名,并通过ServletContext读取读取文件String downloadFileName = "head.jpg"; // 我们这里写死了ServletContext servletContext = getServletContext(); String savePath = servletContext.getRealPath("/WEB-INF/upload"); //以前上传文件保存的目录String downloadPath = savePath + File.separator + downloadFileName; //2.告诉客户端返回的类型String downloadType = servletContext.getMimeType(downloadPath); //获取要下载文件的类型 (这个是image/jpeg)resp.setContentType(downloadType); // (和要下载的类型一样)//3.告诉客户端收到的数据是用于下载的,不是直接显示在页面的// Content-Disposition表示收到的数据怎么处理,attachment表示附件下载使用,filename表示下载文件的名字// filename名可以不和本地的名字一样,当有中文时会乱码,因为http协议设置的的时候不支持中文,需要进行url编码/resp.setHeader("Content-Disposition", "attachment; filename=" + downloadFileName); resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(downloadFileName, "UTF-8")); InputStream resourceAsStream = servletContext.getResourceAsStream(downloadPath); // getResourceAsStream() 传入文件路径,读取文件!!!!!!!!!!!!!// 4.commons-io-1.4.jar中有IOUtils我们可以直接用,不用自己read() write()了ServletOutputStream outputStream = resp.getOutputStream(); // 获取响应的输出流IOUtils.copy(resourceAsStream, outputStream); // 读取输入流的信息复制给输出流,输出给客户端,传入一个输入流和输出流 (字节字符流都行)}
【Servlet文件的上传与下载详解】到此这篇关于Servlet文件的上传与下载详解的文章就介绍到这了,更多相关Servlet上传下载文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- Feign超时|Feign超时 在yml文件里的配置方式
- @51CTO博主们,快来查收你的专属夏日福利!
- 2022 年你手机里有哪些堪称神器的 App()
- 「Node学习笔记」Node.js的模块实现及编译
- 超大规模数据中心内的数据链路层自动测试案例
- 多线程原理和常用方法以及Thread和Runnable的区别
- 数据库数据恢复磁盘空间不足导致sql server故障的数据恢复案例
- 技术分享| 云服务器的使用-nginx的安装及使用
- python爬虫-26-批量爬取表情包,让你斗图再也不会陷入无图可发的窘境
- 昨天面试被问到的 缓存淘汰算法FIFOLRULFU及Java实现