在有些场景中导出前端页面上表格中的数据是通过条件进行精确导出的。
使用GET
请求方式
GET请求方式是比较简单的,简单的处理前端只需要通过一个
a
标签就能实现导出或下载。但是使用GET请求的需要考虑:
检索条件多不多,其次就是如果检索条件拼接在请求URL上会不会超过请求URL的最大长度。如果请求URL的长度超过浏览器的限制长度,浏览器将会将请求自动截断。
GET请求适用于导出所有数据或者是有个把检索条件并且检索条件长度不是特别长的。总之简单导出使用GET请求还是很香的!
或者是考虑采用POST
请求来处理
POST请求的方式做导出比较的麻烦,需要前后端配合来使用,为了确保更好的用户体验(在用户点击导出或下载后,可以看到文件的下载进度),通过流的方式来实现导出或下载。
后端将处理好的数据存储在Excel表格中,读取Excel表格,以流的方式响应给前端;
前端通过
Blob
类型接收,通过window.URL.createObjectURL()
创建源路径,使用document
文档对象创建一个a
标签;为a
标签添加href属性和值(值就是源路径),为a
标签设置download属性和值(值就是被下载的文件名),将指定a
标签节点加到document.body的末尾,最后为a
标签设置一个自触发的点击事件。POST请求最适用于检索条件多的场景
对Excel相关的操作我使用的是阿里巴巴提供的一个工具包
EaxyExcel
,如果你对EasyExcel并没有接触可以通过以下文章进行了解EasyExcel全面教程快速上手
alibaba easyexcel 官方教程,附详细说明、例子、源码
史上最全的Excel导入导出之easyexcel
create table t_brand
(
bid int auto_increment comment '主键ID'
primary key,
bname varchar(255) not null comment '品牌名称'
)
comment '品牌表';
create table t_category
(
cid int auto_increment comment '主键ID'
primary key,
cname varchar(50) null comment '分类名称'
)
comment '分类表';
create table t_products
(
id int auto_increment comment '主键ID'
primary key,
pname varchar(255) not null comment '商品名称',
price double not null comment '商品价格',
flag char not null comment '是否上架标记为:1表示上架、0表示下架',
category_id int not null comment '分类ID',
brand_id int not null,
inventory int not null
)
comment '商品表';
INSERT INTO t_brand (bid, bname) VALUES(1, '华为
');
INSERT INTO t_brand (bid, bname) VALUES(2, '苹果');
INSERT INTO t_brand (bid, bname) VALUES(3, '小米');
INSERT INTO t_brand (bid, bname) VALUES(4, '三星');
INSERT INTO t_brand (bid, bname) VALUES(5, '坚果');
INSERT INTO t_brand (bid, bname) VALUES(6, '1+');
INSERT INTO t_brand (bid, bname) VALUES(7, '锤子');
INSERT INTO t_category (cid, cname) VALUES(1, '手机');
INSERT INTO t_products (id, pname, price, flag, category_id, brand_id, inventory) VALUES(1, '华为P0 Pro', 8999.0, '0', 1, 1, 10000);
INSERT INTO t_products (id, pname, price, flag, category_id, brand_id, inventory) VALUES(2, '华为P1 Pro', 8999.0, '0', 1, 1, 10000);
INSERT INTO t_products (id, pname, price, flag, category_id, brand_id, inventory) VALUES(3, '华为P2 Pro', 8999.0, '0', 1, 1, 10000);
INSERT INTO t_products (id, pname, price, flag, category_id, brand_id, inventory) VALUES(4, '苹果P3 Pro', 8999.0, '0', 1, 1, 10000);
INSERT INTO t_products (id, pname, price, flag, category_id, brand_id, inventory) VALUES(5, '苹果P4 Pro', 8999.0, '0', 1, 1, 10000);
INSERT INTO t_products (id, pname, price, flag, category_id, brand_id, inventory) VALUES(6, '苹果P5 Pro', 8999.0, '0', 1, 1, 10000);
手机
、商品名中包含华为
、价格是在1000-9000之间的所有商品
- 引入相关依赖
<dependency> <groupId>mysqlgroupId> <artifactId>mysql-connector-javaartifactId> <version>5.1.48version> dependency> <dependency> <groupId>com.baomidougroupId> <artifactId>mybatis-plus-boot-starterartifactId> <version>3.3.2version> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>druid-spring-boot-starterartifactId> <version>1.1.9version> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>easyexcelartifactId> <version>2.1.3version> dependency> <dependency> <groupId>io.springfoxgroupId> <artifactId>springfox-swagger2artifactId> <version>2.9.2version> dependency> <dependency> <groupId>io.springfoxgroupId> <artifactId>springfox-swagger-uiartifactId> <version>2.9.2version> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-aopartifactId> dependency> <dependency> <groupId>org.projectlombokgroupId> <artifactId>lombokartifactId> <optional>trueoptional> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>fastjsonartifactId> <version>1.2.61version> dependency>
package com.scholartang.model.po;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@ContentRowHeight(15)//内容的行高
@HeadRowHeight(20)//表头的行高
@ColumnWidth(25)//宽度
@TableName("t_brand")
@ApiModel(description = "品牌表",value = "Brand")
public class Brand extends Model<Brand>{
/**
* 主键ID
*/
@ApiModelProperty(value="主键ID")
@TableId(value = "bid",type = IdType.AUTO)
@ExcelProperty("编号") //设置表头信息
private Integer bid;
/**
* 品牌名称
*/
@ApiModelProperty(value="品牌名称")
@TableField("bname")
@ExcelProperty("名称")
private String bname;
}
package com.scholartang.model.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@ApiModel(description = "分类表",value = "Category")
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName("t_category")
public class Category extends Model<Category> {
/**
* 主键ID
*/
@ApiModelProperty(value="主键ID")
@TableId(value = "cid",type = IdType.AUTO)
private Integer cid;
/**
* 分类名称
*/
@ApiModelProperty(value="分类名称")
@TableField("cname")
private String cname;
}
package com.scholartang.model.po;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@ApiModel(description = "商品类",value = "Products")
@ContentRowHeight(10)
@HeadRowHeight(20)
@ColumnWidth(25)
@TableName("t_products")
public class Products extends Model<Products> {
@ExcelIgnore
@ApiModelProperty(value="主键ID")
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
@ExcelProperty("商品名称")
@ApiModelProperty(value="商品名称")
@TableField("pname")
private String pname;
@ExcelProperty("商品价格")
@ApiModelProperty(value="商品价格")
@TableField("price")
private Double price;
@ExcelProperty("状态")
@ApiModelProperty(value="是否上架标记为:1表示上架、0表示下架")
@TableField("flag")
private String flag;
@ExcelIgnore
@ApiModelProperty(value="分类ID")
@TableField(value = "category_id")
private Integer categoryId;
@ExcelIgnore
@ApiModelProperty(value="品牌ID")
@TableField("brand_id")
private Integer brandId;
@ExcelProperty("库存")
@ApiModelProperty(value="库存")
@TableField("inventory")
private Integer inventory;
@ExcelProperty("分类")
@ApiModelProperty("非表字段:分类名称")
@TableField(exist = false)
private String categoryName;
@ExcelProperty("品牌")
@ApiModelProperty("非表字段:品牌名称")
@TableField(exist = false)
private String brandName;
}
因为只是单纯的导出没有任何的条件,所以使用GET请求处理起来会跟好一些
后端
//controller
@GetMapping("/exportBrand")
public void exportBrand(HttpServletResponse response) throws IOException {
service.exportBrand(response);
}
//service
void exportBrand(HttpServletResponse response) throws IOException;
//serviceImpl
@Override
public void exportBrand(HttpServletResponse response) throws IOException {
List<Brand> brandList = brandMapper.selectList(null);
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码
String fileName = URLEncoder.encode("测试", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(),Brand.class).sheet("data").doWrite(brandList);
}
前端
<el-button type="primary">
<a style="text-decoration: none;color: aliceblue" href="http://localhost:8087/brand/exportBrand">导出品牌信息a>
el-button>
手机
、商品名中包含华为
、价格是在1000-9000之间的所有商品导出数据的检索条件比较多这里采用POST请求的方式来导出Excel文件
后端
//controller
@PostMapping("/filterExportProducts")
public void filterExportProducts(@RequestBody QueryProductsVo queryProductsVo, HttpServletRequest request, HttpServletResponse response) throws Exception{
service.filterExportProducts(queryProductsVo,request,response);
}
//service
void filterExportProducts(QueryProductsVo queryProductsVo,HttpServletRequest request, HttpServletResponse response) throws Exception;
//serviceImpl
@Override
public void filterExportProducts(QueryProductsVo queryProductsVo, HttpServletRequest request, HttpServletResponse response) throws Exception {
//根据条件查询出对应的商品信息
List<Products> productsList = productsMapper.conditionQueryProducts(queryProductsVo.getPname(), queryProductsVo.getBrandId(), queryProductsVo.getCategoryId(), queryProductsVo.getLowestPrice(), queryProductsVo.getHighestPrice());
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
EasyExcel.write(response.getOutputStream(),Products.class).sheet("data").doWrite(productsList);
}
//ProductsMapper
@Results({
@Result(column = "category_id", property = "categoryId"),
@Result(column = "brand_id", property = "brandId"),
@Result(column = "category_id",one = @One(select = "com.scholartang.mapper.CategoryMapper.selectCnameByCid"),property = "categoryName"),
@Result(column = "brand_id",one = @One(select = "com.scholartang.mapper.BrandMapper.selectBnameByBid"),property = "brandName")
})
@Select("")
List<Products> conditionQueryProducts(@Param("pname") String pname,@Param("brandId") Integer brandId,@Param("categoryId") Integer categoryId,@Param("lowestPrice") Double lowestPrice,@Param("highestPrice") Double highestPrice);
//CategoryMapper
@Select("select cname from t_category where cid = #{categoryId}")
String selectCnameByCid(@Param("categoryId") Integer categoryId);
//BrandMapper
@Select("select bname from t_brand where bid = #{brandId}")
String selectBnameByBid(@Param("brandId") Integer brandId);
前端
<el-button type="primary" @click="exportProducts">导出商品信息el-button>
<script>
import axios from 'axios';
export default {
data() {
return {
pageQuery: {
pname: "",
categoryId: "",
brandId: "",
lowestPrice: "",
highestPrice: "",
page: 1,
rows: 10
}
}
},
methods: {
exportProducts() {
axios.post("/products/filterExportProducts", this.pageQuery,{responseType: "blob"}).then(res => {
const content = res.data;
const blob = new Blob([content],{type: "application/vnd.ms-excel;charset=utf-8"})
const fileName = '商品信息.xlsx'
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a')
link.href = url;
link.setAttribute('download',fileName)
document.body.appendChild(link);
link.click();
})
}
}
}
script>