PART1:第一阶段:将上传的excel存储在服务器文件系统的一个绝对路径下,并在前台页面上提供导入导出按钮,能够把存在服务器某个路径下的excel表格等导出来以及把某些文件导入到服务器某个目录下存储起来,其中出现了部分问题并从问题当中学到了经验。
开发步骤:咱们玩的是maven或者说javaweb项目,那么步骤也就是那几步喽,导个jar包或者写个maven依赖坐标,写几个配置文件或者工具类或者XxxTemplate类,供咱们集成某个插件或者技术使用,然后SSM【前台–>controller–>service—>dao+entity+mybatis映射文件中的.xml文件,里面写了很多操作数据库的增删该查】,这不就一条路走通了嘛
- 将上传的excel存储在服务器的一个绝对路径下,并提供下载按钮,能够把存在服务器某个路径下的excel表格等导出来。(在这里当时出现过一个很大的问题就是,之前我们就考虑到说只能存excel没考虑到客户有可能会把txt或者JPG照片等也传上去存下来,隔一段时间再取出来,后来就在项目的工具类中把txt呀、图片呀等都加进去了,就加了一个文件类型判断)
整体前台效果图:
PART1-1:SSM中
- step1:肯定是导入依赖jar包或者直接导入Maven依赖坐标
- step2:前后台代码
- 前台代码:当然,项目中肯定不止这一个或者这一点,不过我在网上找了能体现核心的例程代码,能体现出意思就行
- 后台代码:代码主要逻辑:
-
DownloadController.java
package com.xinhuize.internal.modules.sediment.web.sedimentdata; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.xinhuize.internal.common.config.Global; import com.xinhuize.internal.common.web.BaseController; import com.xinhuize.internal.modules.sediment.entity.sedimentData.SedimentData; @Controller @RequestMapping("${adminPath}/sedimentdata/Download") public class DownloadController extends BaseController { @SuppressWarnings("unused") @RequestMapping("excelDownload") public String excelDownload(HttpSession session, HttpServletResponse response, SedimentData sedimentData, HttpServletRequest request, RedirectAttributes redirectAttributes, Model model) throws IOException { //得到选择的年份,作为第一层文件夹名称 String sedSelectedYear = sedimentData.getSedSelectedYear(); //得到设备名称,作为第二层文件夹名称 String sedimentEquipmentName = sedimentData.getSedimentEquipmentName(); //得到表名,作为第三层文件夹名称 String sedimentTableName = sedimentData.getSedimentTableName(); //String filePath = "D:/xinhuize" + "saveExcel/" + sedSelectedYear + "/" + sedimentEquipmentName + "/" + sedimentTableName + "/";// 文件保存的第一层文件夹 ,组合而来 String filePath = "/usr/local/xinhuize-excel-save" + "/" + sedSelectedYear + "/" + sedimentEquipmentName + "/" + sedimentTableName + "/";// 文件保存的第一层文件夹 ,组合而来 File[] fileListDownLoad = new File(filePath).listFiles(); if (fileListDownLoad == null) { addMessage(redirectAttributes, "下载失败,请联系管理员"); }else { for (File file : fileListDownLoad) { if (file.isFile()) { String name = file.getName(); InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); byte[] buffer = new byte[inputStream.available()]; // int available() 返回值为流中尚未读取的字节的数量 inputStream.read(buffer); String fileName = file.getName();// 获取文件名 response.reset(); response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("utf-8"), "utf-8")); response.addHeader("Content-Length", "" + file.length()); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); if (file.isFile() && file.getName().endsWith(".xls")) { response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); setResponseHeader(response, fileName); response.setHeader("Content-disposition", "attachment;filename=" + fileName); response.setHeader("Access-Control-Expose-Headers", "Content-disposition"); } response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); setResponseHeader(response, fileName); response.setHeader("Content-disposition", "attachment;filename=" + fileName); response.setHeader("Access-Control-Expose-Headers", "Content-disposition"); outputStream.write(buffer); outputStream.flush(); outputStream.close(); inputStream.close(); } } addMessage(redirectAttributes, "下载成功"); } return "redirect:" + Global.getAdminPath() + "/sedimentdata/sedimentData/exportWholeFile?repage"; } public static void setResponseHeader(HttpServletResponse response, String fileName) { try { try { // 设置表文件名的字符编码,不然中文文件名会乱码 fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } response.setContentType("application/octet-stream;charset=utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName); response.addHeader("Pargam", "no-cache"); response.addHeader("Cache-Control", "no-cache"); } catch (Exception ex) { ex.printStackTrace(); } } public void getAllFileName(String path, ListlistFileName) { File file = new File(path); String[] names = file.list(); if (names != null) { String[] completNames = new String[names.length]; for (int i = 0; i < names.length; i++) { completNames[i] = names[i]; listFileName.add(completNames[i]); } } } private String getfilenamelast(String filename) { int start = filename.lastIndexOf("."); if (start != -1) { filename = filename.substring(start, filename.length()); } return filename; } } -
UploadController.java
package com.xinhuize.internal.modules.sediment.web.sedimentdata; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.xinhuize.internal.modules.sediment.entity.sedimentData.SedimentData; @Controller @RequestMapping("${adminPath}/sedimentdata/Upload") public class UploadController { @ResponseBody @RequestMapping("excelUpload") public String excelUpload(HttpServletRequest request, SedimentData sedimentData, RedirectAttributes redirectAttributes, Model model) throws IOException { String isSuccess = null; Mapmap = new HashMap (); //得到选择的年份,作为第一层文件夹名称 String sedSelectedYear = sedimentData.getSedSelectedYear(); //得到设备名称,作为第二层文件夹名称 String sedimentEquipmentName = sedimentData.getSedimentEquipmentName(); //得到表名,作为第三层文件夹名称 String sedimentTableName = sedimentData.getSedimentTableName(); // 转型为MultipartHttpRequest //前台传输过来的上传的文件名 try { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; List fileList = multipartRequest.getFiles("analysisFile"); for (MultipartFile mf : fileList) { if (!mf.isEmpty()) { try { // 文件保存的第二层文件夹 ,以日期(年月日)命名 //String dataName = Tool.getyyyy(); //以上传时的文件名存储 String uploadFileName = mf.getOriginalFilename(); //String filePath = "D:/xinhuize" + "saveExcel/" + sedSelectedYear + "/" + sedimentEquipmentName + "/" + sedimentTableName + "/";// 文件保存的第一层文件夹 ,组合而来 String filePath = "/usr/local/xinhuize-excel-save" + "/" + sedSelectedYear + "/" + sedimentEquipmentName + "/" + sedimentTableName + "/"; File file = new File(filePath); if (!file.exists()) { file.mkdirs(); // 转存文件 三层路径,最后以上传时的文件名存储 mf.transferTo(new File(filePath + uploadFileName)); isSuccess = "ok"; } else { File[] listFiles = file.listFiles(); if (uploadFileName.endsWith(".xlsx") && file != null || listFiles != null || uploadFileName.endsWith(".xls")) { for (int i = 0; i < listFiles.length; i++) { if (listFiles[i].isFile()) { listFiles[i].delete(); } // 转存文件 三层路径,最后以上传时的文件名存储 mf.transferTo(new File(filePath + uploadFileName)); isSuccess = "ok"; } } } } catch (Exception e) { map.put("isok", "0"); e.printStackTrace(); } } } } catch (Exception e) { e.printStackTrace(); } //弹出上传成功的小弹幕字样 //return "redirect:"+Global.getAdminPath()+"/sedimentdata/sedimentData/exportWholeFile?repage"; return isSuccess; } private String getfilenamelast(String filename) { int start = filename.lastIndexOf("."); if (start != -1) { filename = filename.substring(start, filename.length()); } return filename; } protected void addMessage(RedirectAttributes redirectAttributes, String... messages) { StringBuilder sb = new StringBuilder(); for (String message : messages) { sb.append(message).append(messages.length > 1 ? "
" : ""); } redirectAttributes.addFlashAttribute("message", sb.toString()); } } -
Tools.java
package com.xinhuize.internal.modules.sediment.web.sedimentdata; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random; import org.apache.log4j.Logger; public class Tool { private static Logger log = Logger.getLogger(Tool.class); //获取日期 public static String getyyyyMMdd(){ Date d = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); return sdf.format(d); } //获取带毫秒时间戳 public static String getyyyyMMddHHmmssSSS(){ Date d = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); return sdf.format(d); } //获取10000-100000的随机数 public static int getRandom(){ int max=100000; int min=10000; Random random = new Random(); int s = random.nextInt(max)%(max-min+1) + min; return s; } public static String getyyyy(){ Date d = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); return sdf.format(d); } } -
先判断上传的文件是普通表单还是带文件的表单,用ServletFileUpload.isMultipartContent(request)
- 获取ServletFileUpload:ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个Fileltem对象, 在使用ServletFileUpload对象解析请求时需要DiskFileltemFactory对象。所以,我们需要在进行解析工作前构造好DikFileltemFactory对象,通过ServletFileUpload对象的构造方法或setFileltemFactory(方法设置ServletFileUpload对象的fileltemFactory属性。
- 获取ServletFileUpload:ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个Fileltem对象, 在使用ServletFileUpload对象解析请求时需要DiskFileltemFactory对象。所以,我们需要在进行解析工作前构造好DikFileltemFactory对象,通过ServletFileUpload对象的构造方法或setFileltemFactory(方法设置ServletFileUpload对象的fileltemFactory属性。
-
创建上传文件的保存路径,就在WEB-INF下,如果没有则用文件流中的mkdir()方法创建这个目录
-
创建缓存,临时文件,假如文件大小超过了预期的大小,我们就把这个文件放到一个临时文件中然后过几天自动删除,获取提醒用户转存为永久
-
处理上传的文件,一般 都需要通过流来获取,我们可以使用request. getInputStream(),原生态的文件上传流获取:十分麻烦,所以不用这种方法
- 但是我们都建议使用Apache的文件上传组件来实现,common-fileupload, 它需要依赖于commons -io组件,所以呢,咱们就要导jar包或者导入相关的maven依赖;
-
创建DisFileItemFactory对象,处理文件上传路径或者文件大小限制
-
处理上传的文件
PART1-2:SpringBoot中:
-
- 前台代码:当然,项目中肯定不止这一个或者这一点,不过我在网上找了能体现核心的例程代码,能体现出意思就行
- 单个文件上传:
- step1:本来学习一个新技术,就得创建一个demo来测试一下,但是咱们是要往项目中集成,所以就不用新创建一个SpringBoot项目了
- step2:在pom.xml中引入模版引擎等依赖坐标:
- step3:前台那边肯定业务上,比如要搞个按钮呀之类的,处理好,
- step4:然后后台这边就是:创建文件上传的处理控制器,命名为UploadController
- step5:定义好配置文件相关信息,然后在Controller层中写相应代码
spring.servlet.multipart.max-file-size=2MB//这个参数用于限制了上传文件的大小 spring.servlet.multipart.max-request-size=2MB//用于限制了上传请求的大小 file.upload.path=/Users/didi //file.upload.path是上面我们自己定义的用来保存上传文件的路径
- 多个文件上传:
- MultipartFile使用数组,参数名称files对应html页面中input的name,一定要对应
- 后续处理文件的主体(for循环内)跟之前的一样,就是对MultipartFile数组通过循环遍历的方式对每个文件进行存储,然后拼接结果返回信息。
PART2:第二部分,就是用上了OSS,学习到了OSS相关的基础以及使用
- 首先,得先到阿里云控制台,找OSS上面创建一些东西,我自己看作是用来存资源的容器,具体的网络上很多教程
- 然后就可以看到相应的工具栏以及文件夹,就直接可以上传文件并管理文件,勤看官方文档
- 然后就是咱们那些老步骤,
- 写Maven依赖坐标:
com.aliyun.oss aliyun-sdk-oss 2.8.3 org.projectlombok lombok 1.18.4 provided joda-time joda-time 2.9.9 org.apache.commons commons-lang3 3.8.1 - 安装一些插件之类的
- 然后,就是咱们后端的重头戏,写代码呗
- 阿里云OSS配置:在 resource 下新建一个 application-oss.properties
aliyun.endpoint=oss-cn-beijing.aliyuncs.com aliyun.accessKeyId=LTAI5t9mpendCkALZKtBcqW1 aliyun.accessKeySecret=XXX(你的accessKeySecret) aliyun.bucketName=malf-bucket aliyun.urlPrefix=https://malf-bucket.oss-cn-beijing.aliyuncs.com/ spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=1000MB
- 然后到阿里云的OSS概览页面以及其他地方看这些配置信息是啥,不能无脑抄网上
- endpoint、bucketName、urlPrefix 在OSS概览页面就可以看到;
- accessKeyId、accessKeySecret 需要在 Access Key 里面查看。
- 配置类代码,以及controller、service等层代码
- 阿里云OSS配置:在 resource 下新建一个 application-oss.properties
- 写Maven依赖坐标:
巨人的肩膀:
感谢csdn上有意无意被我看到的文章们,感谢这些作者,学习到了很多
https://blog.didispace.com/spring-boot-learning-21-4-3/
https://segmentfault.com/a/1190000040035818



