前言
项目开发中,有时会使用到文件上传与下载功能。项目中提供一个模板供用户下载,用户下载完成后,添加需要的数据内容后,上传到项目中,项目后端接收文件后进行解析,需要存数据库就执行数据库的相关操作。那么如何实现文件的上传与下载功能呢,下面这个案例可供参考(此项目基于springboot,框架采用的是人人权限框架,前后端交互使用ajax通信)。
一、模板文件的下载
1、前端创建模板文件下载链接
<a href="http://localhost:8080/admin/admin/equipment/download/" style="float: right" @click="tip">模板文件下载</a>
//此方法是点击模板文件下载,弹出注意事项。
<script>
var vm = new Vue({
el:'#rrapp',
data:{
},
methods: {
tip: function(){
layer.open({
type: 0,
offset: 'rt',
title: '注意事项'
,content: '设备名称不得为空;经费来源选填(行政、教学、其它)中的一个,分类号和归属单位查看sheet表2;其余可为空。'
});
}
}
});
</script>
2、后端接口编写
添加项目所需依赖
<!-- POI support -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<!-- support xlsx,docx.. -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
<!-- /POI support -->
@RestController
@RequestMapping("admin/equipment")
public class EquipmentController {
/**
* 模板文件下载
* @param response
*/
@SysLog("模板文件下载")
@RequestMapping("/download")
public void download(HttpServletResponse response) {
try {
//获取文件模板
InputStream fis = Thread.currentThread().getContextClassLoader().getResourceAsStream("设备仪器用表.xls");
HSSFWorkbook workbook = new HSSFWorkbook(fis);
//设置文件ContentType类型,这样设置,会自动判断下载文件类型
response.setContentType("application/binary;charset=ISO8859-1");
//转码,免得文件名中文乱码
String fileName = java.net.URLEncoder.encode("设备仪器用表", "UTF-8");
//设置文件下载头
response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls");
ServletOutputStream out = null;
out = response.getOutputStream();
workbook.write(out);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件输出流
}
return;
}
}
3、后端接口中文件模板位置
注意:此模板文件位置位于resources文件夹下,与templates同级。
二、文件上传与导入数据至数据库
1、前端创建文件上传按钮
<a class="btn btn-primary" id="upload"><i class="fa fa-plus"></i> 批量导入</a>
<script>
new AjaxUpload('#upload', {
action: baseURL + "admin/equipment/upload",
name: 'file',
autoSubmit:true,
responseType:"json",
// 告诉jQuery不要去处理发送的数据
processData : false,
// 告诉jQuery不要去设置Content-Type请求头
contentType : false,
onSubmit:function(file, extension){
if (!(extension && /^(xlsx|xls)$/.test(extension.toLowerCase()))){
alert('只支持xlsx、xls格式的Excel文件!');
return false;
}
},
onComplete : function(file, r){
if(r.code == 0){
alert(r.url);
vm.reload();
}else{
alert(r.msg);
}
}
});
</script>
2、实体类
package io.renren.modules.admin.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.renren.common.validator.group.AddGroup;
import io.renren.common.validator.group.UpdateGroup;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
/**
* 设备表
*
* @author yzs
* @email [email protected]
* @date 2020-11-19 15:26:13
*/
@Data
@TableName("equipment")
public class EquipmentEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId
private Long id;
/**
* 设备编号
*/
private String number;
/**
* 分类号
*/
private String classnum;
/**
* 分类名
*/
@TableField(exist = false)
@NotBlank(message="分类名不能为空", groups = {
AddGroup.class, UpdateGroup.class})
private String classname;
/**
* 设备名称
*/
private String name;
/**
* 型号
*/
private String model;
/**
* 规格
*/
private String specification;
/**
* 单价
*/
private Double price;
/**
* 厂商
*/
private String vendor;
/**
* 出厂号
*/
private String factorynum;
/**
* 购置日期
*/
private Date time;
/**
* 经费来源
*/
private String funding;
/**
* 归属单位编号
*/
private String deptnum;
/**
* 归属单位名称
*/
@TableField(exist = false)
private String deptname;
/**
* 状态(0未分配 1已分配 2已报废)
*/
private Integer status;
}
3、后端接口编写
@RestController
@RequestMapping("admin/equipment")
public class EquipmentController {
@Autowired
private EquipmentService equipmentService;
/**
* 上传文件
*/
@SysLog("上传文件")
@RequestMapping("/upload")
public R upload(@RequestParam("file") MultipartFile file) throws Exception {
if (file.isEmpty()) {
throw new RRException("上传文件不能为空");
}
FileInputStream inputStream = (FileInputStream) file.getInputStream();
//用于存储解析后的Excel文件
Workbook workbook = new HSSFWorkbook(inputStream);
//得到表
Sheet sheet = workbook.getSheetAt(0);
//获取标题内容
// Row rowTitle = sheet.getRow(1);
// if (rowTitle != null){
// int cellCount = rowTitle.getPhysicalNumberOfCells();
// for (int cellNum=0; cellNum<cellCount; cellNum++){
// Cell cell = rowTitle.getCell(cellNum);
// if (cell != null){
// int cellType = cell.getCellType();
// String cellValue = cell.getStringCellValue();
// }
// }
// }
//获取内容信息
int rowCount = sheet.getPhysicalNumberOfRows();
for (int rowNum=1; rowNum<rowCount; rowNum++){
Row rowData = sheet.getRow(rowNum);
if (rowData != null) {
EquipmentEntity equipmentEntity = new EquipmentEntity();
//设备编号
String number = String.valueOf(rowData.getCell(0));
if(number == "null"){
number = UUID.randomUUID().toString().substring(0,8);
equipmentEntity.setNumber(number);
}else {
number = number.substring(0,number.indexOf("."));
equipmentEntity.setNumber(number);
}
//设备名称
String name = String.valueOf(rowData.getCell(1));
if (name == "null"){
equipmentEntity.setName(name);
}else {
name = name.substring(0,name.indexOf("."));
equipmentEntity.setName(name);
}
//分类号
String classnum = String.valueOf(rowData.getCell(2));
if (classnum == "null"){
equipmentEntity.setClassnum(classnum);
}else {
classnum = classnum.substring(0,classnum.indexOf("."));
equipmentEntity.setClassnum(classnum);
}
//型号
String model = String.valueOf(rowData.getCell(3));
if(model == "null"){
equipmentEntity.setModel(model);
}else {
model = model.substring(0,model.indexOf("."));
equipmentEntity.setModel(model);
}
//规格
String specification = String.valueOf(rowData.getCell(4));
if (specification == "null"){
equipmentEntity.setSpecification(specification);
}else {
specification = specification.substring(0,specification.indexOf("."));
equipmentEntity.setSpecification(specification);
}
//单价
String jiage = String.valueOf(rowData.getCell(5));
if (jiage != "null") {
Double price = Double.valueOf(String.valueOf(jiage));
equipmentEntity.setPrice(price);
}
//厂商
String vendor = String.valueOf(rowData.getCell(6));
if (vendor == "null"){
equipmentEntity.setVendor(vendor);
}else {
vendor = vendor.substring(0,vendor.indexOf("."));
equipmentEntity.setVendor(vendor);
}
//出厂号
String factorynum = String.valueOf(rowData.getCell(7));
if (factorynum == "null"){
equipmentEntity.setFactorynum(factorynum);
}else {
factorynum = factorynum.substring(0,factorynum.indexOf("."));
equipmentEntity.setFactorynum(factorynum);
}
//购置日期
Date time = rowData.getCell(8).getDateCellValue();
if(time != null) {
equipmentEntity.setTime(time);
}else {
equipmentEntity.setTime(new Date());
}
//经费来源
String funding = String.valueOf(rowData.getCell(9));
equipmentEntity.setFunding(funding);
//归属单位
String deptnum = String.valueOf(rowData.getCell(10));
if (deptnum == "null"){
equipmentEntity.setDeptnum(deptnum);
}else {
deptnum = deptnum.substring(0,deptnum.indexOf("."));
equipmentEntity.setDeptnum(deptnum);
}
//设置设备仪器的默认属性值,状态为未分配
equipmentEntity.setStatus(0);
equipmentService.save(equipmentEntity);
}
}
//关闭流
inputStream.close();
return R.ok().put("url","成功");
}
}
注意:此处进行数据库存储的过程是比较占用内存的,性能待优化,原因在于读取上传文件内容时,通过遍历文件分行读取,每读取一行信息便进行数据库存取操作。有多少行,便进行多少次IO操作,性能不好。
三、总结
以上就是今天要讲的内容,本文仅仅简单介绍了使用java代码实现文件上传与文件下载,希望可以帮到你们。