序言

现在,绝大部分的应用程序在很多的情况下都需要使用到文件上传与下载的功能,在本文中结合hap利用spirng mvc实现文件的上传和下载,包括上传下载图片、上传下载文档。前端所使用的技术不限,本文重点在于后端代码的实现。希望可以跟随我的一步步实践,最终轻松掌握在hap中的文件上传和下载的具体实现。

案例

1.  数据库设计

表结构

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------

-- Table structure for tb_fruit

-- ----------------------------

DROP TABLE IF EXISTS `tb_fruit`;

CREATE TABLE `tb_fruit` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`fruitName` varchar(255) DEFAULT NULL,

`picturePath` varchar(255) DEFAULT NULL,

`filePath` varchar(255) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

字段描述

Id 主键自增

fruitName 水果名称

picturePath 图片路径

filePath 附件2.  先使用代码生成工具根据表结构生成对应的测试

 dto层:


  1. package hbi.core.test.dto;
  2. /**Auto Generated By Hap Code Generator**/
  3. import com.hand.hap.mybatis.annotation.ExtensionAttribute;
  4. import org.hibernate.validator.constraints.Length;
  5. import javax.persistence.GeneratedValue;
  6. import javax.persistence.Id;
  7. import javax.persistence.Table;
  8. @Table(name = "tb_fruit")
  9. public class Fruit{
  10. public static final String FIELD_ID = "id";
  11. public static final String FIELD_FRUITNAME = "fruitname";
  12. public static final String FIELD_PICTUREPATH = "picturepath";
  13. public static final String FIELD_FILEPATH = "filepath";
  14. @Id
  15. @GeneratedValue
  16. private Long id;
  17. @Length(max = 255)
  18. private String fruitname;
  19. @Length(max = 255)
  20. private String picturepath;
  21. @Length(max = 255)
  22. private String filepath;
  23. //省略get/set方法...
  24. }
  25. controller层:
  26. package hbi.core.test.controllers;
  27. import com.hand.hap.attachment.exception.FileReadIOException;
  28. import com.hand.hap.core.IRequest;
  29. import com.hand.hap.core.exception.TokenException;
  30. import com.hand.hap.system.controllers.BaseController;
  31. import com.hand.hap.system.dto.ResponseData;
  32. import hbi.core.test.dto.Fruit;
  33. import hbi.core.test.service.IFruitService;
  34. import net.sf.json.JSONObject;
  35. import org.apache.commons.lang.StringUtils;
  36. import org.springframework.beans.factory.annotation.Autowired;
  37. import org.springframework.stereotype.Controller;
  38. import org.springframework.validation.BindingResult;
  39. import org.springframework.web.bind.annotation.*;
  40. import org.springframework.web.multipart.MultipartFile;
  41. import javax.servlet.http.HttpServletRequest;
  42. import javax.servlet.http.HttpServletResponse;
  43. import java.io.*;
  44. import java.net.URLEncoder;
  45. import java.text.SimpleDateFormat;
  46. import java.util.*;
  47. @Controller
  48. public class FruitController extends BaseController {
  49. @Autowired
  50. private IFruitService service;
  51. /**
  52. * word文件路径
  53. */
  54. private String wordFilePath="/u01/document/userfile";
  55. /**
  56. * 图片文件路径
  57. */
  58. private String userPhotoPath = "/u01/document/userphoto";
  59. /**
  60. * 文件最大 5M
  61. */
  62. public static final Long FILE_MAX_SIZE = 5*1024*1024L;
  63. /**
  64. * 允许上传的图片格式
  65. */
  66. public static final List<String> IMG_TYPE = Arrays.asList("jpg", "jpeg", "png", "bmp");
  67. /**
  68. * 允许上传的文档格式
  69. */
  70. public static final List<String> DOC_TYPE = Arrays.asList("pdf", "doc", "docx");
  71. /**
  72. * ContentType
  73. */
  74. public static final Map<String, String> EXT_MAPS = new HashMap<>();
  75. static {
  76. // image
  77. EXT_MAPS.put("jpg", "image/jpeg");
  78. EXT_MAPS.put("jpeg", "image/jpeg");
  79. EXT_MAPS.put("png", "image/png");
  80. EXT_MAPS.put("bmp", "image/bmp");
  81. // doc
  82. EXT_MAPS.put("pdf", "application/pdf");
  83. EXT_MAPS.put("ppt", "application/vnd.ms-powerpoint");
  84. EXT_MAPS.put("doc", "application/msword");
  85. EXT_MAPS.put("doc", "application/wps-office.doc");
  86. EXT_MAPS.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
  87. }
  88. /**
  89. * @author jiaqing.xu@hand-china.com
  90. * @date 2017/9/4 17:23
  91. * @param wordFile photoFile fruitName
  92. * @return List<Fruit>
  93. * @description 保存水果信息
  94. */
  95. @RequestMapping(value = {"/api/public/upload/fruit/submit"}, method = RequestMethod.POST)
  96. @ResponseBody
  97. public List<Fruit> fruitSubmit(@RequestParam(value = "wordFile", required = true) MultipartFile wordFile,@RequestParam(value = "photoFile", required = true) MultipartFile photoFile, @RequestParam(value="fruitName",required = true) String fruitName,HttpServletRequest request){
  98. IRequest requestContext = createRequestContext(request);
  99. //上传word文件到磁盘
  100. Map<String,Object> result1 = uploadFile(wordFile,wordFilePath,DOC_TYPE,null);
  101. //上传图片文件到磁盘
  102. Map<String, Object> result2 = uploadFile(photoFile,userPhotoPath, IMG_TYPE, 200);
  103. List<Fruit> list = new ArrayList<>();
  104. //如果创建成功则保存相应路径到数据库
  105. if((boolean)result1.get("success")&&(boolean)result2.get("success")){
  106. Fruit fruit = new Fruit();
  107. fruit.setFruitname(fruitName);
  108. //设置图片路径
  109. fruit.setPicturepath((String) result2.get("path"));
  110. //设置附件路径
  111. fruit.setFilepath((String) result1.get("path"));
  112. //插入
  113. fruit = service.insertSelective(requestContext,fruit);
  114. list.add(fruit);
  115. }
  116. return list;
  117. }
  118. /**
  119. * @author jiaqing.xu@hand-china.com
  120. * @date 2017/9/4 16:18
  121. * @param
  122. * @return
  123. * @description 【通用】 上传文件到磁盘的某一个目录
  124. */
  125. public Map<String, Object> uploadFile(MultipartFile file, String path, List<String> fileTypes, Integer ratio){
  126. Map<String, Object> results = new HashMap<>();
  127. results.put("success", false);
  128. if(file == null || file.getSize() < 0 || StringUtils.isBlank(file.getOriginalFilename())){
  129. results.put("message", "文件为空");
  130. return results;
  131. }
  132. if(file.getSize() > FILE_MAX_SIZE){
  133. results.put("message", "文件最大不超过" + FILE_MAX_SIZE/1024/1024 + "M");
  134. return results;
  135. }
  136. String originalFilename = file.getOriginalFilename();
  137. if(!fileTypes.contains(originalFilename.substring(originalFilename.lastIndexOf(".")+1))){
  138. results.put("message", "文件格式不正确");
  139. return results;
  140. }
  141. SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");
  142. String datetime = formatter.format(new Date());
  143. String yearmonth = datetime.substring(0, 6);
  144. // 在基础路径上加上年月路径
  145. String fileDir = path + "/" + yearmonth;
  146. // 文件名以 [_时间戳_随机数#原文件名]的形式 随机数防止重复文件名
  147. String randomNumber = String.valueOf((Math.random() * 90000) + 10000).substring(0, 5);
  148. String fileName = "_" + datetime + randomNumber + "=" + originalFilename;
  149. // 文件路径
  150. String filePath = fileDir + "/" + fileName;
  151. try {
  152. // 创建目录
  153. File dir = new File(fileDir);
  154. if(!dir.exists() && !dir.isDirectory()){
  155. dir.mkdirs();
  156. }
  157. // 文件输入流
  158. InputStream is = file.getInputStream();
  159. // 输出流
  160. OutputStream os = new FileOutputStream(filePath);
  161. // 输出文件到磁盘
  162. int len = 0;
  163. byte[] buffer = new byte[2048];
  164. while((len = is.read(buffer, 0, 2048)) != -1){
  165. os.write(buffer, 0, len);
  166. }
  167. os.flush();
  168. os.close();
  169. is.close();
  170. //向结果中保存状态消息和存储路径
  171. results.put("success", true);
  172. results.put("message", "SUCCESS");
  173. results.put("path", filePath);
  174. // 压缩图片
  175. if(ratio != null){
  176. //ImgExif.ExifInfoToRotate(filePath);
  177. ImgCompress imgCompress = new ImgCompress(filePath);
  178. imgCompress.setFileName(filePath);
  179. imgCompress.resizeByWidth(ratio);
  180. }
  181. } catch (Exception e) {
  182. e.printStackTrace();
  183. results.put("message", "ERROR");
  184. return results;
  185. }
  186. return results;
  187. }
  188. /**
  189. * @author jiaqing.xu@hand-china.com
  190. * @date 2017/9/4 17:23
  191. * @param
  192. * @return
  193. * @description 【通用】 读取上传的文件 将文件以流的形式输出
  194. */
  195. @RequestMapping(value = "/api/public/read/file")
  196. public void readFile(@RequestParam String path, HttpServletResponse response) throws FileReadIOException, TokenException {
  197. Map<String, Object> results = new HashMap<>();
  198. try {
  199. File file = new File(path);
  200. if(!file.exists()){
  201. results.put("success", false);
  202. results.put("message", "文件不存在");
  203. JSONObject jsonObject = JSONObject.fromObject(results);
  204. response.getWriter().write(jsonObject.toString());
  205. return;
  206. }
  207. // 类型
  208. String contentType = EXT_MAPS.get(path.substring(path.lastIndexOf(".") + 1));
  209. // 设置头
  210. response.addHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(path.substring(path.indexOf("=") + 1), "UTF-8") + "\"");
  211. response.setContentType(contentType + ";charset=UTF-8");
  212. response.setHeader("Accept-Ranges", "bytes");
  213. // 输出文件
  214. InputStream is = new FileInputStream(file);
  215. OutputStream os = response.getOutputStream();
  216. int len = 0;
  217. byte[] buffer = new byte[2048];
  218. while ((len = is.read(buffer, 0, 2048)) != -1){
  219. os.write(buffer, 0, len);
  220. }
  221. os.flush();
  222. os.close();
  223. is.close();
  224. } catch (IOException e) {
  225. e.printStackTrace();
  226. }
  227. }
  228. }

说明:

(1)文件保存路径wordFilePath、 水果照片保存路径userPhotoPath可以通过配置文件进行配置。

(2)其中保存的文件的路径在项目的根路径下,比如我的项目在D盘的某一个文件夹下,则生成的word文件的位置为D盘/u01/document/userfile路径下.

3.  postman测试

注意点:在使用postman测试时,使用post请求,参数中body为form-data,依次将需要的参数填写到对应的位置。

返回后的数据为插入数据库中的记录。

4.  运行结果

数据库中插入的新的记录:

磁盘中的word文件:

磁盘中的图片:

浏览器进行下载测试:

http://localhost:8080/api/public/read/file?path=/u01/document/userphoto/201709/_2017090417503366053845=大西瓜.jpg

基于hap的文件上传和下载的更多相关文章

  1. 基于jsp的文件上传和下载

    参考: 一.JavaWeb学习总结(五十)--文件上传和下载 此文极好,不过有几点要注意: 1.直接按照作者的代码极有可能listfile.jsp文件中 <%@taglib prefix=&qu ...

  2. koa2基于stream(流)进行文件上传和下载

    阅读目录 一:上传文件(包括单个文件或多个文件上传) 二:下载文件 回到顶部 一:上传文件(包括单个文件或多个文件上传) 在之前一篇文章,我们了解到nodejs中的流的概念,也了解到了使用流的优点,具 ...

  3. java web学习总结(二十四) -------------------Servlet文件上传和下载的实现

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  4. (转载)JavaWeb学习总结(五十)——文件上传和下载

    源地址:http://www.cnblogs.com/xdp-gacl/p/4200090.html 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传 ...

  5. JavaWeb学习总结,文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  6. java文件上传和下载

    简介 文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到 ...

  7. JavaWeb学习总结(五十)——文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  8. JavaWeb——文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  9. JavaWeb学习 (二十八)————文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

随机推荐

  1. HTML 事件属性(摘自菜鸟教程)

    HTML 事件属性 全局事件属性 HTML 4 的新特性之一是可以使 HTML 事件触发浏览器中的行为,比方说当用户点击某个 HTML 元素时启动一段 JavaScript. 如果你想学习更多关于事件 ...

  2. 深入理解 Handler 消息机制

    记得很多年前的一次面试中,面试官问了这么一个问题,你在项目中一般如何实现线程切换? 他的本意应该是考察 RxJava 的使用,只是我的答案是 Handler,他也就没有再追问下去了.在早期 Andro ...

  3. Python 之父的解析器系列之六:给 PEG 语法添加动作

    原题 | Adding Actions to a PEG Grammar 作者 | Guido van Rossum(Python之父) 译者 | 豌豆花下猫("Python猫"公 ...

  4. Mybatis系列(一)入门

    Mybatis系列(一)入门 mybatis简介 MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结 ...

  5. FreeSql (二十一)查询返回数据

    FreeSql 采用 ExpressionTree 优化读取速读,如果懂技术的你一定知道 .NETCore 技术下除了原生代码,最快就是 Emit 和 ExpressionTree. 项目在初期使用的 ...

  6. Net基础篇_学习笔记_第十天_方法_方法的调用问题

    在Main()函数中,调用Test()函数,我们管Main()函数称之为调用者,管Test()函数称之为被调用者.如果被调用者想要得到调用者的值:1).传递参数.2).使用静态字段来模拟全局变量.如果 ...

  7. SSO-CAS实现单点登录服务端

    目录 CAS-SSO 一.单点登录-CAS 二.下载搭建CAS 1. 下载 CAS 5.3 2. 导入IDEA 3. 打包war 3. war包部署到Tomcat 4. 启动Tomcat,访问 htt ...

  8. python中os模块再回顾

    先看下我的文件目录结构 F:\PYTHON项目\ATM购物车\7月28 在此目录下的文件如下: 封装.py 模块os.sys复习.py 运行当前的文件是模块os.sys复习.py 1.获取当前文件所在 ...

  9. CentOS安装TeamViewer

    在https://www.teamviewer.com/en/download/linux/ 选择合适的host版本. wget https://download.teamviewer.com/dow ...

  10. oracle 11g 下载安装 使用记录

    Oracle 11g 使用记录 1.下载oracle快捷安装版:   (1)下载连接:https://pan.baidu.com/s/1ClC0hQepmTw2lSJ2ODtL7g 无提取码 (2)去 ...