序言

现在,绝大部分的应用程序在很多的情况下都需要使用到文件上传与下载的功能,在本文中结合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文件:

磁盘中的图片:

浏览器进行下载测试:

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. MySQL运行时自动生成的性能相关的数据参考

      某大师曾说过,一个DBA要像熟悉自己的老婆一样熟悉自己的数据库,个人认为包含了两个方面的熟悉: 1,在稳定性层面来说,更多的是关注高可用.读写分离.负载均衡,灾备管理等等high level层面的 ...

  2. (六)分布式通信----MessagePack序列化

    1. .Net Core的序列化方式 1.1 json.Net 常用的工具包,如Newtonsoft.Json, 它是基于json格式的序列化和反序列化的组件 json.net 有以下优点: 侵入性: ...

  3. 体验SpringCloud Gateway

    Spring Cloud Gateway是Spring Cloud技术栈中的网关服务,本文实战构建一个SpringCloud环境,并开发一个SpringCloud Gateway应用,快速体验网关服务 ...

  4. TK可视化之文件内容查找

    1.内容输出类 import tkinter import python基础.day15.搜索数据可视化.BigDataFind class InputViem(): def __init__(sel ...

  5. Codeforces Round #503 (by SIS, Div. 2) D. The hat -交互题,二分

    cf1020D 题意: 交互题目,在有限的询问中找到一个x,使得数列中的第x位和第(x+n/2)位的值大小相同.数列保证相邻的两个差值为1或-1: 思路: 构造函数f(x) = a[x] - a[x ...

  6. HDU-3549Flow Problem 最大流模板题

    传送门 这里是Ford-Fulkerson写的最大流模板 #include <iostream> #include <cstdio> #include <algorith ...

  7. SPOJ - 3267. D-query 主席树求区间个数

    SPOJ - 3267 主席树的又一种写法. 从后端点开始添加主席树, 然后如果遇到出现过的元素先把那个点删除, 再更新树, 最后查询区间就好了. #include<bits/stdc++.h& ...

  8. lightoj 1283 - Shelving Books(记忆化搜索+区间dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1283 题解:这题很显然一看就像是区间dp,但是单纯的区间dp好像解决不了问题可 ...

  9. 【Redis】集群方式

    一.概述 1.1 Redis3.0版本之前 1.2 常见集群方案 二.Redis-Cluster原理 三.搭建集群方案 3.1 准备工作 3.2 创建模拟集群的文件夹 3.3 复制脚本 3.4 复制一 ...

  10. 【Offer】[34] 【二叉树中和为某一值的路径】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径.从树的根节点开始往下一直到叶节点所经过的节点形成一条路径.  ...