开发过程中遇到一个导出图片的需求,项目用的是easypoi插件,其官网写的实在太模糊,大概是为了避免菜鸟用easypoi拉低插件逼格。参考网上一位巨佬的文章,搞了半天终于出来,在此特意感谢那个巨佬。
Easypoi官方教程:http://doc.wupaas.com/docs/easypoi/easypoi-1c0u4mo8p4ro8
我的做法是根据图片的链接地址,将图片资源下载成二进制字节数组保存起来,然后导出Excel。
1. 前端
<!--HTML-->
<button type="button" id="excelOutBtn" class="btn btn-sm bg-orange">
<i class="fa fa-cloud-download fa-btn"></i> 导出
</button>
<!--JS-->
<script type="text/javascript">
// 导出
$("#excelOutBtn").click(function () {
window.location.href = "/projectName/aaa/bbb/excelOut";
});
</script>
2. 导出实体
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@ExcelTarget("ImageInfo")
public class ImageInfo{
@Excel(name = "图片名称", width = 20)
private String imgName;
@Excel(name = "图片路径", width = 40)
private String imgUrl;
/**
type =2 该字段类型为图片
imageType=1 (默认可以不填)表示从file读取,字段类型是个字符串类型,
可以用相对路径也可以用绝对路径、绝对路径优先依次获取。
imageType=2 表示从数据库或者已经读取完毕,字段类型是个字节数组,直接使用,
同时image 类型的cell最好设置好宽和高,会百分百缩放到cell那么大,不是原尺寸。
**/
@TableField(exist = false)
@Excel(name = "图片", type = 2, width = 60, height = 60, imageType = 2)
private byte[] imgFile;
}
3. 根据URL下载图片工具 HttpImgUtils
/**
* @author gmd
* @description 网络图片下载工具
* @date 2020年9月18日09:34:41
*/
@Slf4j
public class HttpImgUtils {
/**
* 获取网络图片转成字节流
* @param strUrl 完整图片地址
* @return 图片资源数组
*/
public static byte[] getNetImgByUrl(String strUrl) {
try {
URL url = new URL(strUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(2 * 1000);
// 通过输入流获取图片数据
InputStream inStream = conn.getInputStream();
// 得到图片的二进制数据
byte[] btImg = readInputStream(inStream);
return btImg;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 从输入流中获取字节流数据
* @param inStream 输入流
* @return 图片流
*/
private static byte[] readInputStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
// 设置每次读取缓存区大小
byte[] buffer = new byte[1024*10];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
inStream.close();
return outStream.toByteArray();
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
String url = "https://www.baidu.com/img/flexible/logo/pc/result.png";
System.out.println(getNetImgByUrl(url));
}
}
4. Controller层实现
@GetMapping("aaa/bbb/excelOut")
public void excelOut(HttpServletResponse response, @RequestParam Map para) {
List<ImageInfo> result = imgService.selectExcelList(para);
for (ImageInfo img : result) {
try {
img.setImgFile(HttpImgUtils.getNetImgByUrl(img.getImgUrl()));
// 路径无效则无法下载图片资源,导致该字段为NULL
if (img.getImgFile() == null) {
// 如果该图片资源不存在,则给默认的图片资源
Img.setImgFile(HttpImgUtils.getNetImgByUrl("https://www.baidu.com/img/logo.jpg"));
}
} catch (Exception e) {
log.error("导出文件_图片资源获取失败 url = "+img.getImgUrl);
continue;
}
}
String fileName = "图片信息表.xls";
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("图片信息", "图片信息"), ImageInfo.class, result);
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(outputStream);
} catch (IOException e) {
log.error("导出图片失败");
throw new RuntimeException(e);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
至此,导出功能就完成了。