基于hap的文件上传和下载
序言
现在,绝大部分的应用程序在很多的情况下都需要使用到文件上传与下载的功能,在本文中结合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层:
package hbi.core.test.dto; /**Auto Generated By Hap Code Generator**/ import com.hand.hap.mybatis.annotation.ExtensionAttribute; import org.hibernate.validator.constraints.Length; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Table(name = "tb_fruit") public class Fruit{ public static final String FIELD_ID = "id"; public static final String FIELD_FRUITNAME = "fruitname"; public static final String FIELD_PICTUREPATH = "picturepath"; public static final String FIELD_FILEPATH = "filepath"; @Id @GeneratedValue private Long id; @Length(max = 255) private String fruitname; @Length(max = 255) private String picturepath; @Length(max = 255) private String filepath; //省略get/set方法... } controller层:
package hbi.core.test.controllers; import com.hand.hap.attachment.exception.FileReadIOException; import com.hand.hap.core.IRequest; import com.hand.hap.core.exception.TokenException; import com.hand.hap.system.controllers.BaseController; import com.hand.hap.system.dto.ResponseData; import hbi.core.test.dto.Fruit; import hbi.core.test.service.IFruitService; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.*; @Controller public class FruitController extends BaseController { @Autowired private IFruitService service; /** * word文件路径 */ private String wordFilePath="/u01/document/userfile"; /** * 图片文件路径 */ private String userPhotoPath = "/u01/document/userphoto"; /** * 文件最大 5M */ public static final Long FILE_MAX_SIZE = 5*1024*1024L; /** * 允许上传的图片格式 */ public static final List<String> IMG_TYPE = Arrays.asList("jpg", "jpeg", "png", "bmp"); /** * 允许上传的文档格式 */ public static final List<String> DOC_TYPE = Arrays.asList("pdf", "doc", "docx"); /** * ContentType */ public static final Map<String, String> EXT_MAPS = new HashMap<>(); static { // image EXT_MAPS.put("jpg", "image/jpeg"); EXT_MAPS.put("jpeg", "image/jpeg"); EXT_MAPS.put("png", "image/png"); EXT_MAPS.put("bmp", "image/bmp"); // doc EXT_MAPS.put("pdf", "application/pdf"); EXT_MAPS.put("ppt", "application/vnd.ms-powerpoint"); EXT_MAPS.put("doc", "application/msword"); EXT_MAPS.put("doc", "application/wps-office.doc"); EXT_MAPS.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); } /** * @author jiaqing.xu@hand-china.com * @date 2017/9/4 17:23 * @param wordFile photoFile fruitName * @return List<Fruit> * @description 保存水果信息 */ @RequestMapping(value = {"/api/public/upload/fruit/submit"}, method = RequestMethod.POST) @ResponseBody 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){ IRequest requestContext = createRequestContext(request); //上传word文件到磁盘 Map<String,Object> result1 = uploadFile(wordFile,wordFilePath,DOC_TYPE,null); //上传图片文件到磁盘 Map<String, Object> result2 = uploadFile(photoFile,userPhotoPath, IMG_TYPE, 200); List<Fruit> list = new ArrayList<>(); //如果创建成功则保存相应路径到数据库 if((boolean)result1.get("success")&&(boolean)result2.get("success")){ Fruit fruit = new Fruit(); fruit.setFruitname(fruitName); //设置图片路径 fruit.setPicturepath((String) result2.get("path")); //设置附件路径 fruit.setFilepath((String) result1.get("path")); //插入
fruit = service.insertSelective(requestContext,fruit);
list.add(fruit);
}
return list; } /** * @author jiaqing.xu@hand-china.com * @date 2017/9/4 16:18 * @param * @return * @description 【通用】 上传文件到磁盘的某一个目录 */ public Map<String, Object> uploadFile(MultipartFile file, String path, List<String> fileTypes, Integer ratio){ Map<String, Object> results = new HashMap<>(); results.put("success", false); if(file == null || file.getSize() < 0 || StringUtils.isBlank(file.getOriginalFilename())){ results.put("message", "文件为空"); return results; } if(file.getSize() > FILE_MAX_SIZE){ results.put("message", "文件最大不超过" + FILE_MAX_SIZE/1024/1024 + "M"); return results; } String originalFilename = file.getOriginalFilename(); if(!fileTypes.contains(originalFilename.substring(originalFilename.lastIndexOf(".")+1))){ results.put("message", "文件格式不正确"); return results; } SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String datetime = formatter.format(new Date()); String yearmonth = datetime.substring(0, 6); // 在基础路径上加上年月路径 String fileDir = path + "/" + yearmonth; // 文件名以 [_时间戳_随机数#原文件名]的形式 随机数防止重复文件名 String randomNumber = String.valueOf((Math.random() * 90000) + 10000).substring(0, 5); String fileName = "_" + datetime + randomNumber + "=" + originalFilename; // 文件路径 String filePath = fileDir + "/" + fileName; try { // 创建目录 File dir = new File(fileDir); if(!dir.exists() && !dir.isDirectory()){ dir.mkdirs(); } // 文件输入流 InputStream is = file.getInputStream(); // 输出流 OutputStream os = new FileOutputStream(filePath); // 输出文件到磁盘 int len = 0; byte[] buffer = new byte[2048]; while((len = is.read(buffer, 0, 2048)) != -1){ os.write(buffer, 0, len); } os.flush(); os.close(); is.close(); //向结果中保存状态消息和存储路径 results.put("success", true); results.put("message", "SUCCESS"); results.put("path", filePath); // 压缩图片 if(ratio != null){ //ImgExif.ExifInfoToRotate(filePath); ImgCompress imgCompress = new ImgCompress(filePath); imgCompress.setFileName(filePath); imgCompress.resizeByWidth(ratio); } } catch (Exception e) { e.printStackTrace(); results.put("message", "ERROR"); return results; } return results; } /** * @author jiaqing.xu@hand-china.com * @date 2017/9/4 17:23 * @param * @return * @description 【通用】 读取上传的文件 将文件以流的形式输出 */ @RequestMapping(value = "/api/public/read/file") public void readFile(@RequestParam String path, HttpServletResponse response) throws FileReadIOException, TokenException { Map<String, Object> results = new HashMap<>(); try { File file = new File(path); if(!file.exists()){ results.put("success", false); results.put("message", "文件不存在"); JSONObject jsonObject = JSONObject.fromObject(results); response.getWriter().write(jsonObject.toString()); return; } // 类型 String contentType = EXT_MAPS.get(path.substring(path.lastIndexOf(".") + 1)); // 设置头 response.addHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(path.substring(path.indexOf("=") + 1), "UTF-8") + "\""); response.setContentType(contentType + ";charset=UTF-8"); response.setHeader("Accept-Ranges", "bytes"); // 输出文件 InputStream is = new FileInputStream(file); OutputStream os = response.getOutputStream(); int len = 0; byte[] buffer = new byte[2048]; while ((len = is.read(buffer, 0, 2048)) != -1){ os.write(buffer, 0, len); } os.flush(); os.close(); is.close(); } catch (IOException e) {
e.printStackTrace();
}
}
}
说明:
(1)文件保存路径wordFilePath、 水果照片保存路径userPhotoPath可以通过配置文件进行配置。
(2)其中保存的文件的路径在项目的根路径下,比如我的项目在D盘的某一个文件夹下,则生成的word文件的位置为D盘/u01/document/userfile路径下.
3. postman测试

注意点:在使用postman测试时,使用post请求,参数中body为form-data,依次将需要的参数填写到对应的位置。
返回后的数据为插入数据库中的记录。
4. 运行结果
数据库中插入的新的记录:

磁盘中的word文件:

磁盘中的图片:

浏览器进行下载测试:

基于hap的文件上传和下载的更多相关文章
- 基于jsp的文件上传和下载
参考: 一.JavaWeb学习总结(五十)--文件上传和下载 此文极好,不过有几点要注意: 1.直接按照作者的代码极有可能listfile.jsp文件中 <%@taglib prefix=&qu ...
- koa2基于stream(流)进行文件上传和下载
阅读目录 一:上传文件(包括单个文件或多个文件上传) 二:下载文件 回到顶部 一:上传文件(包括单个文件或多个文件上传) 在之前一篇文章,我们了解到nodejs中的流的概念,也了解到了使用流的优点,具 ...
- java web学习总结(二十四) -------------------Servlet文件上传和下载的实现
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- (转载)JavaWeb学习总结(五十)——文件上传和下载
源地址:http://www.cnblogs.com/xdp-gacl/p/4200090.html 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传 ...
- JavaWeb学习总结,文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- java文件上传和下载
简介 文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到 ...
- JavaWeb学习总结(五十)——文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- JavaWeb——文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- JavaWeb学习 (二十八)————文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
随机推荐
- Linux Centos虚拟机扩容(/dev/mapper/centos-root)
1:.首先查看我们的根分区大小是多少 df -h 文件系统 类型 容量 已用 可用 已用% 挂载点 /dev/mapper/centos-root xfs 18G 1.1G 17G 6% / devt ...
- HTML(一)简介,元素
HTML简介 html实例: <!DOCTYPE html> 菜鸟教程 我的第一个标题 我的第一个段落 实例解析: <!DOCTYPE html> 声明为 HTML5 文档,不 ...
- c# autofac结合WebApi的使用
一.下载相关类库引用 install-package Autofac install-package Autofac.Mvc4 install-package Autofac.WebApi2 二.配置 ...
- Eclipse批量注释、批量缩进、批量取消缩进技巧
1.批量注释:选中若干行,按"Ctrl"+"/" 2.批量缩进:选中若干行,按TAB 3.批量取消缩进:选中若干行,按SHIFT+TAB
- 2019牛客暑期多校训练营(第二场) - J - Go on Strike! - 前缀和预处理
题目链接:https://ac.nowcoder.com/acm/contest/882/C 来自:山东大学FST_stay_night的的题解,加入一些注释帮助理解神仙代码. 好像题解被套了一次又一 ...
- NOIP 2016 组合数问题 题解
一道sb题目,注意范围,可打表解决,打出杨辉三角,在用前缀和求解即可 代码(一维前缀和) #include<bits/stdc++.h> using namespace std; int ...
- 用C#实现的几种常用数据校验方法整理(CRC校验;LRC校验;BCC校验;累加和校验)
CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错 ...
- 【Offer】[40] 【最小的K个数】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入n个整数,找出其中最小的k个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 牛客网刷题地 ...
- c++调试在容器释放内存时报Unknown Signal 或 Trace/breakpoint trap异常
在做一道题时,用到的板子中出现了很多的容器的使用,,一开始都是开MAXN大小的容器,,但是有几率出现程序运行完后不正常退出,, 在多次尝试断点调试后,发现主要的异常是程序在结束时,要进行资源的释放,, ...
- VSTO之WPF和Winform弹窗
写插件弹窗是肯定要有的,有弹窗才有展示功能的页面啊! 记录一下前段时间遇到的一些弹窗方面的坑,一个个踩过来也是收获颇丰啊! WPF弹窗 最简单的弹窗方式,new一个窗体,然后调用Show方法. Win ...