提示:图片压缩下载
SpringBoot+Vue批量下载图片压缩包
前言
项目中遇到上传的图片需要下载下来,并且是以压缩包的格式。因此记录下来,给自己以及小伙伴们。
提示:以下是本篇文章正文内容,下面案例可供参考
后台正文
controller
/**
* 教师信息Controller
*
* @author milletsoft
* @date 2022-08-30
*/
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@RestController
@RequestMapping("/jsgl/jsxxb")
public class JsJsxxbController extends BaseController {
/**
* 导出照片
*/
@PostMapping("/downloadJSImg")
public void downJSImg(@RequestBody JsJsxxb jsJsxxb){
jsJsxxbService.downloadJSImg(jsJsxxb);
}
}
impl
/**
* 教师照片导出
*
* @param jsJsxxb 导出教师照片
*/
@Override
public void downloadJSImg(JsJsxxb jsJsxxb) {
String namingFormat = jsJsxxb.getDcmmgs();
//根据条件先查询符合条件的数据
List<JsJsxxb> list = jsJsxxbMapper.selectDownLoadImg(jsJsxxb);
//声明一个存储路径的List
List<Map<String, String>> paths = new ArrayList<Map<String, String>>();
list.forEach(JsJsxxb -> {
String imagePrefix = getImagePrefix(JsJsxxb,namingFormat);
paths.add(GenerateImageUtil.GenerateImage(GenerateImageUtil.ByteStreamToBase64(JsJsxxb.getTxs()),imagePrefix));
});
try {
DownloadZipUtil.download(paths,"教师照片_"+System.currentTimeMillis(),response);
} catch (Exception e) {
e.printStackTrace();
}
}
提示:生成图片的格式也可以控制 png jpg
1.我的代码中 namingFormat 是导出的命名格式,前端选择是身份证那就获取用户身份证号作为生成的图片的名称。例如: 12345678901234567.png
2.list.forEach 去遍历查询回来的数据 。getImagePrefix方法中会判断namingFormat ,为空就获取当前时间戳作为生成图片的名称。例如: 1294890876859.png 代码如下:
/**
* 得到图像前缀
*
* JsJsxxb jsJsxxb
*/
public String getImagePrefix(JsJsxxb jsJsxxb, String namingFormat) {
String prefix = new String();
if (StringUtils.isNotBlank(namingFormat)){
switch (namingFormat) {
case "zgh": {
prefix = jsJsxxb.getZgh();
break;
}
case "sfzh": {
prefix = jsJsxxb.getSfzh();
break;
}
default: {
prefix = String.valueOf(System.currentTimeMillis());
}
}
}else{
prefix = String.valueOf(System.currentTimeMillis());
}
return prefix;
}
生成图片。代码如下:
paths.add(GenerateImageUtil.GenerateImage(GenerateImageUtil.ByteStreamToBase64(JsJsxxb.getTxs()),imagePrefix));
生成的图片也先要转为Base64字符串
//就是这串代码
GenerateImageUtil.ByteStreamToBase64(JsJsxxb.getTxs())
生成图片
//就是这串代码 需要两个参数,一个是图片的Base64字符串,一个是生成图片的名称
GenerateImageUtil.GenerateImage()
工具类代码:
import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Decoder;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
/**
* 生成图片工具类
* Created by gs01 on 2022-09-07.
*/
public class GenerateImageUtil {
/**
* Base64字符串进行解码并生成图片
*
*/
public static HashMap<String, String> GenerateImage(String imgStr, String namingFormat) {
if (imgStr == null) // 图像数据为空
return null;
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] b = decoder.decodeBuffer(imgStr);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {// 调整异常数据
b[i] += 256;
}
}
//生成图片名称
String imgFilePath;
if (StringUtils.isNotBlank(namingFormat)){
imgFilePath = "d://"+namingFormat+".jpg";
}else{
imgFilePath = "d://"+System.currentTimeMillis()+".jpg";
}
//将生成的图片的路径存到Map集合
HashMap<String, String> map = new HashMap<>();
map.put("filePath",imgFilePath);
OutputStream out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
// return true;
return map;
} catch (Exception e) {
return null;
}
}
/**
* 字节流转Base64
*
*/
public static String ByteStreamToBase64(byte[] array){
String imgBase64 = "";
byte[] zpBlob = array;
if (zpBlob != null) {
byte[] encodeBase64 = Base64.encodeBase64(zpBlob);
//Base64图片
imgBase64 = new String((encodeBase64));
}
return imgBase64;
}
}
到这里图片就生成了,在你的D盘下。下面这段代码就是生成的路径:
//生成图片名称
String imgFilePath;
if (StringUtils.isNotBlank(namingFormat)){
//后面的 .jpg就是生成的图片的格式
imgFilePath = "d://"+namingFormat+".jpg";
}else{
//后面的 .jpg就是生成的图片的格式
imgFilePath = "d://"+System.currentTimeMillis()+".jpg";
}
然后就是去调用压缩工具类压缩图片
try {
DownloadZipUtil.download(paths,"教师照片_"+System.currentTimeMillis(),response);
} catch (Exception e) {
e.printStackTrace();
}
“教师照片_”+System.currentTimeMillis() 是压缩包文件名称
下面是压缩包工具类 代码如下:
import com.ruoyi.framework.config.RuoYiConfig;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @Author: autumn
* @Date: 2022/4/2
*/
public class DownloadZipUtil {
public static void download(List<Map<String, String>> paths,String zipName,HttpServletResponse response) throws Exception{
if (paths.size() != 0) {
// 创建临时路径,存放压缩文件
String zipFilePath = RuoYiConfig.getProfile()+"/temp.zip";
// 压缩输出流,包装流,将临时文件输出流包装成压缩流,将所有文件输出到这里,打成zip包
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath));
// 循环调用压缩文件方法,将一个一个需要下载的文件打入压缩文件包
for (Map<String, String> path : paths) {
// 该方法在下面定义
try {
fileToZip(path, zipOut);
} catch (IOException e) {
e.printStackTrace();
}
}
// 压缩完成后,关闭压缩流
zipOut.close();
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition","filename=" + percentEncode(zipName));
response.setHeader(" Content-Type","application/octet-stream;charset=UTF-8");
//该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭
ServletOutputStream outputStream = response.getOutputStream();
FileInputStream inputStream = new FileInputStream(zipFilePath);
// 如果是SpringBoot框架,在这个路径
// org.apache.tomcat.util.http.fileupload.IOUtils产品
// 否则需要自主引入apache的 commons-io依赖
// copy方法为文件复制,在这里直接实现了下载效果
IOUtils.copy(inputStream, outputStream);
// 关闭输入流
inputStream.close();
//下载完成之后,删掉这个zip包
File fileTempZip = new File(zipFilePath);
fileTempZip.delete();
}
}
public static String percentEncode(String s) throws UnsupportedEncodingException{
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
public static void fileToZip(Map<String, String> filePath,ZipOutputStream zipOut) throws IOException {
// 需要压缩的文件
File file = new File(filePath.get("filePath"));
// 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName
String fileName = file.getName();
FileInputStream fileInput = new FileInputStream(filePath.get("filePath"));
// 缓冲
byte[] bufferArea = new byte[1024 * 10];
BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10);
// 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称
String[] split = fileName.split("\\.");
//压缩的图片的名称
// String newFileName = fileName+"."+split[1];
// String ss = fileName.substring(0,fileName.lastIndexOf("."));
zipOut.putNextEntry(new ZipEntry(fileName));
int length = 0;
// 最常规IO操作,不必紧张
while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
zipOut.write(bufferArea, 0, length);
}
//关闭流
fileInput.close();
// 需要注意的是缓冲流必须要关闭流,否则输出无效
bufferStream.close();
// 压缩流不必关闭,使用完后再关
File f = new File (String.valueOf(file));
//压缩文件生成后把磁盘生成的图片删除
//图片存在,可执行删除操作
if (f.exists()==true){
Boolean flag = false;
flag = file.delete();
//成功删除图片
if (flag){
//删除失败
}else {
}
//图片不存在,终止操作
}else{
}
}
}
到这里图片压缩包就生成了
前端正文
代码如下(示例):
//导出教师照片
toDownLoadTeacherPhoto(){
axios({
contentType:'application/json;charset=UTF-8',
method: 'post',
url: "/dev-api/jsgl/jsxxb/downloadJSImg",//你的下载的接口路径
data: this.queryParams,//放参数的 图片命名格式啊
type:'json',
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() },
}).then(async (res) => {
const blob = new Blob([res.data],
{ type: 'application/zip' }
)
var downloadElement = document.createElement('a')//创建一个a 虚拟标签
var href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download =
decodeURI(
res.headers['content-disposition'].split(' ')[0].replace("filename=","")
// '失败明细.txt'
) || '' // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href);
})
},
谷歌下载之后会直接打开,火狐会在左下角显示压缩包
完事。有建议的小伙伴或者有问题的小伙伴可以留言,感谢童鞋的浏览。
总结
1.图片生成也需要先转为Base64字符串
2.生成的图片和压缩包要记得删除
3.response的响应一定要设置。
4.图片,压缩包,生成路径
5.图片名称,图片格式