在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现。
先说下要求:
PC端全平台支持,要求支持Windows,Mac,Linux
支持所有浏览器。
支持文件批量上传
支持文件夹上传,且要求在服务端保留层级结构。文件夹数量要求支持到10W。
支持大文件断点续传,要求刷新浏览器,重启浏览器,重启电脑后仍然能够继续上传。文件大小要求能够支持到50个G。
支持自动加载本地文件,要求能够自动加载指定的本地文件。
支持文件批量下载,要求不要在服务器打包。因为50G的文件在服务器打包时间比较长。
支持文件夹下载,要求不要在服务器打包,下载到本地后要求保留层级结构
文件列表面板支持路径导航,新建文件夹
对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
一、开发环境搭建
创建一个FileUploadAndDownLoad项目,加入Apache的commons-fileupload文件上传组件的相关Jar包,如下图所示:
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
依赖jar包如下
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
二、实现文件上传
前台HTML模板
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
文件块处理逻辑如下
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
保存文件块逻辑如下
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
web.xml配置如下
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
运行效果如下:
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
文件面板逻辑
前台代码
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
2.3、文件上传的细节
上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的
1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。
4、要限制上传文件的最大值。
5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
针对上述提出的5点细节问题,我们来改进一下UploadHandleServlet,改进后的代码如下:
文件数据表结构
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
文件夹数据表结构
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
下载数据表结构
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
针对上述提出的5点小细节问题进行改进之后,我们的文件上传功能就算是做得比较完善了。
三、文件下载
加载文件列表,注意,这里只列出上传完的文件和文件夹,没有上传完的就不列出了
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
数据库的处理逻辑比较简单,注意一下SQL语句中的条件即可
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
我们要将Web应用系统中的文件资源提供给用户进行下载,首先我们要有一个页面列出上传文件目录下的所有文件,当用户点击文件下载超链接时就进行下载操作,编写一个ListFileServlet,用于列出Web应用系统中所有下载文件。
文件列表加载逻辑
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
这里简单说一下ListFileServlet中listfile方法,listfile方法是用来列出目录下的所有文件的,listfile方法内部用到了递归,在实际开发当中,我们肯定会在数据库创建一张表,里面会存储上传的文件名以及文件的具体存放目录,我们通过查询表就可以知道文件的具体存放目录,是不需要用到递归操作的,这个例子是因为没有使用数据库存储上传的文件名和文件的具体存放位置,而上传文件的存放位置又使用了散列算法打散存放,所以需要用到递归,在递归时,将获取到的文件名存放到从外面传递到listfile方法里面的Map集合当中,这样就可以保证所有的文件都存放在同一个Map集合当中。
编写一个用于处理文件下载的Servlet,DownLoadServlet的代码如下:
文件管理器主要逻辑如下:
文件管理器所有的逻辑都在PageFileMgr.java中实现。
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
另外,文件管理器有一些相关的配置在data目录下
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
系统配置数据如下
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
路径配置如下
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
文件管理器的脚本处理全部放在index.js中
![点击并拖拽以移动](/i/l/?n=22&i=blog/2441432/202210/2441432-20221025160357448-484219704.gif)
关于JavaWeb中的文件上传和下载功能的内容就这么多。
示例下载地址:up6-jsp-springboot: Web大文件上传-jsp-springboot示例 - Gitee.com