java实现文件上传和文件查看、下载
在一个应用系统里,会有上传本地文件到系统服务器里或从系统服务器查看、下载有关文件到本地的需要。这里只对自己了解到的做一个总结
文件上传
这里是把本地文件上传到服务器文件目录,而不是放到项目目录里。
前端用的bootstrap和Jquery,上传文件界面显示在是模态框里
//文件上传
<input id="uploadFile" type="file" name="file" style="margin-left: 90px; margin-top: 10px">
<!-- 模态框 --><div class="modal fade" id="newImg"><div class="modal-dialog"><div class="modal-content"><div class="modal-header">上传新的流程图</div><!-- <form class="form-horizontal"> --><div class="modal-body"><div class="form-group"><label for="inputEmail" class="col-sm-2 control-label">添加描述</label><div class="col-sm-10"><input id="describle" type="text"class="form-control list-inline" /></div></div><div class="form-group"><label class="control-label" style="margin-left: 30px">待上传的文件</label><div style="margin-left: 20px"><label class="control-label">输入记录id</label> <input type="text" id="relId_ajax" name="relId_ajax"><input id="uploadFile" type="file" name="file" style="margin-left: 90px; margin-top: 10px"></div></div><div class="modal-footer"><button id="back_btn" class="btn btn-danger" data-dismiss="modal">取消</button><button class="btn btn-success" onclick="submit_btn()" data-dismiss="modal">上传</button></div></div><!-- </form> --></div></div></div>
点击上传之后。调用JS方法使用ajax方法进行上传。上传成功之后,接收到后端返回的信息,并再次调用ajax请求对这些信息进行处理。这些信息后面会提到
//上传新的流程图(单文件上传,ajax方式)function submit_btn(){var relId = $("#relId_ajax").val();var fileDescribe = $("#describle").val();var file = $("#uploadFile")[0].files[0];var formData = new FormData();formData.append("file", file);formData.append("relId", relId);formData.append("fileDescribe", fileDescribe);$.ajax({dataType : "JSON",contentType : "application/json;charset=UTF-8",type : "POST",data : formData,url : "/hzsh/eomc-front/file/multiUpload",processData : false, // 使数据不做处理contentType : false, // 不要设置Content-Type请求头success : function(result) {console.log(result)console.log(result.msg)var JsonData = JSON.parse(result.data) //将后端传回的json数组字符串转换为json对象 //[{"fileName":"compareWithAll.PNG","id":"4b267540-1d97-4703-85b8-6522ee26843f"}]var imgId = JsonData[0].id;console.log(imgId); $.ajax({type:"post",url:"/hzsh/eomc-zzhj/nyglms/updateImg",data:{"imgId":imgId},success:function(result){console.log("进行流程图更新")if(result.code){alert("上传成功")}else{alert("上传失败")}}})},error : function() {console.log("上传出错");}})}
效果如图:(这里我上传的是图片)
点击上传之后,会先将文件保存到数据库的附件表里,这张表就是对上传的文件元数据做统一的管理,包括文件类型、文件原名、文件大小、上传时间、上传用户等等。因为考虑到文件安全问题,上传的文件经过后端处理,存到服务器端文件目录里的文件名是一串随机字符串序列。
@RequestMapping("/file/multiUpload")public String multiUpload(HttpServletRequest request, HttpServletResponse response,HttpSession session) {try {String userName = (String) session.getAttribute("userName");String fileDescribe = request.getParameter("fileDescribe");String relId = request.getParameter("relId");String sort = request.getParameter("sort");log.info("文件描述" + fileDescribe);List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");boolean result = true;String retMsg = "";JSONArray retDataArray = new JSONArray();for (int i = 0; i < files.size(); i++) {MultipartFile file = files.get(i);if (file.isEmpty()) {retMsg += "第" + (i + 1) + "个文件为空";continue;}String fileName = file.getOriginalFilename();//定义附件表对象,用于将上传的文件元数据写入附件表CommAttachEntity commAttachEntity = new CommAttachEntity();commAttachEntity.setId(UUID.randomUUID().toString());commAttachEntity.setRealName(fileName);commAttachEntity.setEncName(commAttachEntity.getId());int extendIndex = fileName.indexOf(".");if(extendIndex < 0) {extendIndex = 0;}commAttachEntity.setExtendName(fileName.substring(extendIndex));if(CDataUtil.isPicture(fileName)) {commAttachEntity.setFileType("图片");}else if(CDataUtil.isDocument(fileName)) {commAttachEntity.setFileType("文档");}else {commAttachEntity.setFileType("未知");}commAttachEntity.setFlgDel("0");commAttachEntity.setFileSize(file.getSize() + "");commAttachEntity.setCreateUser(userName);commAttachEntity.setCreateDate(CDateTimeUtil.sysDateTime("yyyy-MM-dd HH:mm:ss"));commAttachEntity.setRemark(fileDescribe);commAttachEntity.setRelId(relId);if(sort == null || sort.trim().equals("")) {commAttachEntity.setSort(i + "");}else {commAttachEntity.setSort(sort);}//文件输出到本地File dest = new File(EnvConstant.attachPath + commAttachEntity.getEncName());try {file.transferTo(dest);log.info("第" + (i + 1) + "个文件上传成功(" + fileName + ")");} catch (Exception e) {log.error("第" + (i + 1) + "个文件上传失败(" + fileName + ")" + e.toString(), e);result = false;retMsg += fileName + ";";}//写入附件表commAttachMapper.insert(commAttachEntity);JSONObject retDataJson = new JSONObject();retDataJson.put("id", commAttachEntity.getId());retDataJson.put("fileName", fileName);retDataArray.add(retDataJson);}System.out.println(retDataArray+"KKKKKKKKKKKKKKKKKKK");if(result) {System.out.println("上传成功");return CIOUtil.buildRetMsg(true, "上传成功", retDataArray);}else {return CIOUtil.buildRetMsg(false, retMsg + " 文件上传失败", retDataArray);}}catch(Exception e) {return CIOUtil.buildRetMsg(false, "文件上传出错", e.getMessage());}}
上面这段代码就是对前端发送来的文件进行处理,生成一些文件元数据保存到数据库对应的附件表里。附件表主键就是在这里生成的随机序列:UUID.randomUUID()
该接口代码处理完文件信息后一方面将文件元数据传到数据库,
//写入附件表commAttachMapper.insert(commAttachEntity);
一方面将文件保存到对应的文件目录里,其中 EnvConstant.attachPath 是之前在类中定义好的
文件保存路径
//文件输出到本地File dest = new File(EnvConstant.attachPath + commAttachEntity.getEncName());file.transferTo(dest);
另一方面向前端返回一些信息
if(result) {System.out.println("上传成功");return CIOUtil.buildRetMsg(true, "上传成功", retDataArray);}else {return CIOUtil.buildRetMsg(false, retMsg + " 文件上传失败", retDataArray);}
像前端返回的信息里包含了很重要的一项,就是随机生成的文件序列,也是文件上传后保存到服务器端目录里的文件加密名,这里的ajax请求是在点击“上传”后的JS方法里,是一个回调请求。
success : function(result) {console.log(result)console.log(result.msg)var JsonData = JSON.parse(result.data) //将后端传回的json数组字符串转换为json对象 //[{"fileName":"compareWithAll.PNG","id":"4b267540-1d97-4703-85b8-6522ee26843f"}]var imgId = JsonData[0].id;console.log(imgId); $.ajax({type:"post",url:"/hzsh/eomc-zzhj/nyglms/updateImg",data:{"imgId":imgId},success:function(result){console.log("进行流程图更新")if(result.code){alert("上传成功")}else{alert("上传失败")}}})},
将随机生成的文件字符串序列保存到业务表里,作为外键和附件表进行关联。因为这里模拟的是特定业务的文件上传,业务里文件只有一个,所以上传文件属于更新操作。文件信息保存到业务表里始终只有一条记录。
@ResponseBody@RequestMapping("/nyglms/updateImg")public String updateNyglmsImg(HttpServletRequest request, HttpServletResponse response, HttpSession session) {// 获取CommAttachEntity对象流程图的Id信息String imgId = request.getParameter("imgId");// 将CommAttachEntity的流程图id信息写到nyglms表中String userName = (String) session.getAttribute("userName");DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Calendar calendar = Calendar.getInstance();String create_img_time = df.format(calendar.getTime());EomcZzhjNyglmsEntity eomcZzhjNyglmsEntity = new EomcZzhjNyglmsEntity();eomcZzhjNyglmsEntity.setId(1);eomcZzhjNyglmsEntity.setCreateImgUser(userName);eomcZzhjNyglmsEntity.setCreateImgTime(create_img_time);eomcZzhjNyglmsEntity.setImgId(imgId);int result = eomcZzhjNyglmsService.updateNyglmsImg(eomcZzhjNyglmsEntity);if (result == 1) {return CIOUtil.buildRetMsg(true, "上传成功", null);} else {return CIOUtil.buildRetMsg(false, "上传失败,请重新上传", null);}}
文件查看
此时,文件上传操作已经完成。当我们想在功能模块里查看已上传的文件时,只需发送请求到后端的业务表里获取唯一的文件随机字符串序列,并将字符串序列和文件保存路径进行拼接。这里使用IO流的方式将特定文件写出到前端页面。
@ResponseBody@RequestMapping("/nyglms/queryImg")public String queryNyglmsImage(HttpServletRequest request, HttpServletResponse response) {// 获取最新上传的流程图片信息(从业务表中)EomcZzhjNyglmsEntity eomcZzhjNyglmsEntity = eomcZzhjNyglmsService.queryNyglmsImg();String imgId = eomcZzhjNyglmsEntity.getImgId();System.out.println("查询流程图************************:"+imgId);try {File file = new File(EnvConstant.attachPath +imgId);FileInputStream fis = new FileInputStream(file);OutputStream out = response.getOutputStream();long size = file.length();byte[] temp = new byte[(int) size];fis.read(temp, 0, (int) size);fis.close();byte[] data = temp;response.setContentType("image/PNG");// data = Base64.encodeBase64(data);out.write(data);out.flush();out.close();} catch (Exception e) {e.printStackTrace();}return CIOUtil.buildRetMsg(true, "显示流程图成功", null);}
前端代码:
<div><img id="Img" alt="" src="/nyglms/queryImg" style="height: 400px; width: 600px;" /></div>
文件下载
可以从附件表获取文件随机字符串序列,也可以从业务表中获取。
这里从业务表中获取更容易一些(点击前端下载按钮,调用该后端接口)
/*** a根据附件名称,下载附件* @param fileName* @param request* @param response* @param model* @return*/@RequestMapping("/file/download")public String download( HttpServletRequest request, HttpServletResponse response ,Model model) {// 获取最新上传的流程图片信息(从业务表中)EomcZzhjNyglmsEntity eomcZzhjNyglmsEntity = eomcZzhjNyglmsService.queryNyglmsImg();String imgId = eomcZzhjNyglmsEntity.getImgId();if(getImgId== null || getImgId.trim().equals("")) {log.info("imgId为空,无法下载附件");return CIOUtil.buildRetMsg(false, "imgId不能为空", null);}//设置为png格式的文件setHeader(request, response, imgId);byte[] buff = new byte[1024];//创建缓冲输入流BufferedInputStream bis = null;OutputStream outputStream = null;try {outputStream = response.getOutputStream();//这个路径为待下载文件的路径bis = new BufferedInputStream(new FileInputStream(new File(EnvConstant.attachPath + imgId)));int read = bis.read(buff);//通过while循环写入到指定了的文件夹中(这里指浏览器设置的目录文件夹)while (read != -1) {outputStream.write(buff, 0, buff.length);outputStream.flush();read = bis.read(buff);}} catch ( IOException e ) {e.printStackTrace();//出现异常返回给页面失败的信息model.addAttribute("result","下载失败");return "下载失败";} finally {if (bis != null) {try {bis.close();} catch (IOException e) {e.printStackTrace();}}if (outputStream != null) {try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}}//成功后返回成功信息model.addAttribute("result","下载成功");return CIOUtil.buildRetMsg(true, "下载成功", null);}private boolean setHeader(HttpServletRequest request, HttpServletResponse response, String fileName) {try {response.setContentType("application/octet-stream");response.setHeader("content-type", "application/octet-stream");String browser = request.getHeader("User-Agent");if (-1 < browser.indexOf("MSIE 6.0") || -1 < browser.indexOf("MSIE 7.0")) {// IE6, IE7 浏览器response.addHeader("content-disposition", "attachment;filename="+ new String(fileName.getBytes(), "ISO8859-1"));} else if (-1 < browser.indexOf("MSIE 8.0")) {// IE8response.addHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8"));} else if (-1 < browser.indexOf("MSIE 9.0")) {// IE9response.addHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8"));} else if (-1 < browser.indexOf("Chrome")) {// 谷歌response.addHeader("content-disposition","attachment;filename*=UTF-8''" + URLEncoder.encode(fileName, "UTF-8"));} else if (-1 < browser.indexOf("Safari")) {// 苹果response.addHeader("content-disposition", "attachment;filename="+ new String(fileName.getBytes(), "ISO8859-1"));} else {// 火狐或者其他的浏览器response.addHeader("content-disposition","attachment;filename*=UTF-8''" + URLEncoder.encode(fileName, "UTF-8"));}return true;} catch (Exception e) {log.error(e.getMessage());return false;}}
java实现文件上传和文件查看、下载相关推荐
- java文件上传_Java文件上传细讲
什么是文件上传? 文件上传就是把用户的信息保存起来. 为什么需要文件上传? 在用户注册的时候,可能需要用户提交照片.那么这张照片就应该要进行保存. 上传组件(工具) 为什么我们要使用上传工具? 为啥我 ...
- 渗透测试 ( 0 ) --- XSS、CSRF、文件上传、文件包含、反序列化漏洞
漏洞数据库:https://www.exploit-db.com/google-hacking-database 1.渗透测试 实用 浏览器插件 chrome.edge 插件:搜索 cookie,安装 ...
- 文件上传时,文件太大会有几种被限制的情况
文件上传时,文件太大会有几种被限制的情况 近期在维护一个项目时,商户有反馈,在新增用户时会直接卡住并报错,返回一个异常,应用层没有日志,最后排查出来是nginx限制了请求的最大值. 那么整个链 ...
- 通达OA未授权任意文件上传及文件包含漏洞分析学习
今年3月份通达OA爆出了文件上传和文件包含漏洞,网络上很多复现和分析的博客,今天我也来试着分析分析,据360灵腾安全实验室判断该漏洞等级为高,利用难度低,威胁程度高,所以可能比较适合代码审计的新手来练 ...
- 文件上传漏洞_通达OA前台任意文件上传漏洞+文件包含漏洞导致getshell
点击蓝字|关注我们 通达OA前台任意文件上传漏洞 +文件包含漏洞导致getshell 一.漏洞介绍/Profile/ 通达OA介绍: 通达OA(Office Anywhere网络智能办公系统)是由北京 ...
- 文件上传、文件包含和目路遍历杂谈
一.说明 文件上传.文件包含和目路遍历是<黑客防线>盛行的时代常谈的getshell手法,但到现在的安全书藉感觉就比较少提及或一笔带过.在谈的年代看不懂,在看得懂的年代又不谈了,概念感觉总 ...
- httpclient base64 文件上传_文件上传下载
说道文件上传下载,这个业务需求并不是很复杂思想如下 1.将文件上传到 某台服务器上的指定的路径下也可以这样理解 文件上传就是将本地图片发送到别的地方,下载就是将别的地方的图片放在本地 2.将路径同文件 ...
- 踩坑 - click事件与blur事件冲突问题 input文件上传同名文件问题
前言 上周写需求遇到了一点小坑涉及到一些小细节,今天赶上没啥事总结一下分享出来. click事件与blur事件冲突问题 click事件与blur事件 blur事件: 表单事件,元素失去焦点时候触发,不 ...
- 代码审计:YCCMS 代码执行 文件上传 任意文件删除
代码审计:YCCMS 代码执行 文件上传 任意文件删除 YCCMS 审计准备 代码审计 代码执行漏洞 文件上传漏洞 任意文件删除漏洞 YCCMS YCCMS是一款PHP版轻量级CMS建站系统,程序页面 ...
- Dropzone单文件上传、多文件上传、文件夹上传,springmvc接收,上传至Minio的一系列问题
0 前言 1.项目需要上传文件和大量的文件夹,页面只有一个input file标签会很丑,偶然间得知dropzone类库, 决定使用. 2. 项目后端采用springmvc接收,调用minio代码上传 ...
最新文章
- 力扣(LeetCode)刷题,简单题(第12期)
- 极客新闻——17、给决定长久做程序员的你三个建议
- 推荐10个能带来快感的实用windows软件,好评如潮!
- CF 529B Group Photo 2 (online mirror version)
- nginx linux脚本,shell脚本之nginx自动化脚本
- css 带轮廓的圆,CSS3 圆球轮廓动画
- leetcode 449. Serialize and Deserialize BST | 449. 序列化和反序列化二叉搜索树(BST后序遍历性质)
- 计算机文档用什么翻译,Word文档翻译在哪里(适于Word2010-Word2016)?
- Linux基础(1)--Vim编辑器的常用命令
- ubuntu18.04,Linux使用远程连接工具连接失败解决
- 学习C++项目——一个基于C++11简单易用的轻量级网络编程框架 1
- delphi控件属性大全-详解-简介
- 开放源代码是如何吞噬软件的
- 数据可视化大屏的应用与落地实践
- 软链接解决存储空间不足
- 魔兽世界正式服哪个服务器稳定,魔兽世界正式服什么职业厉害2021
- Node.js 和npm的安装(插件的安装)
- base64图片压缩到指定大小
- 解决windows下C32ASM反汇编无法打开的问题
- JAVASE温故知新
热门文章
- HDU 1281 棋盘游戏 【二分图最大匹配】
- centos7.2 使用rpm安装jdk8
- 扭曲效果 效率优化 GrapPass,CommandBuffer对比
- python 打印输出xml数据问题
- Linux学习之CentOS6下Mysql数据库的安装与配置
- JSon_零基础_005_将po(bean)对象转换为JSon格式的对象字符串,返回给界面
- Excel的python读写
- java怎么进行浮点数运算_【考试经验】Java中实现浮点数的精确运算
- ORA-01810格式代码出现两次 的解决方案
- Linux常用命令——关机重启命令