我遇到三个问题
1、ts封装axios,responseType设置 blob 但加上去无效。
2、vue main.js用到了mock ,加上去responseType返回类型会自动去掉。
3、下载压缩文件时 报错Access-Control-Allow-Origin
index.vue重要部分代码
//导出zip文件
getCertificateCode(formModel.value.pcid).then((response) => {
const name=((1+Math.random())*0x10000)
const link = document.createElement('a')
const blob = new Blob([response.data], { type: 'application/zip' })
const url = window.URL.createObjectURL(blob)
link.href = url
link.download = [name, '.zip'].join('') // 重命名文件
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
.catch((e) => {
Message.error('暂无相关证书');
});
};
//导出xls文件
const downloadscore = () => {
if (!formModel.value.pcid) {
Message.error('请选择批次');
return;
}
getScoreCodescore(formModel.value.pcid)
.then((res) => {
const name=((1+Math.random())*0x10000)
const elink = document.createElement('a')
elink.style.display = 'none'
const blob = new Blob([res.data])
const blobUrl = URL.createObjectURL(blob)
elink.href = blobUrl
elink.download = [name, '.xls'].join('') // 重命名文件
document.body.appendChild(elink)
elink.click()
document.body.removeChild(elink)
})
.catch((e) => {
console.log(e);
Message.error('暂无相关文件');
});
};
js 部分代码,我用的是ts封装axios 提供了多种方式
export class Axios {
constructor(config?: AxiosRequestConfig);
defaults: AxiosDefaults;
interceptors: {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
};
getUri(config?: AxiosRequestConfig): string;
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
get<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
delete<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
head<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
options<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
post<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
put<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
patch<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
}
//调用zip流的接口
export function getCertificateCode(pcid) {
return axios.request({
url: '/sria/certificateCode',
method: 'get',
params:{ pcid:pcid },
responseType:'blob',
})
}
//调用xls流的接口
export function getScoreCodescore(pcid) {
return axios.request({
url: '/sria/scoreCode',
method: 'get',
params:{ pcid:pcid },
responseType:'blob',
})
}
response返回结果判断并返回
// add response interceptors
axios.interceptors.response.use(
(response) => {
......省略代码......
if(response.status===200){
if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') {
return response;
}
}
......省略代码......
return res;
},
(error) => {
Message.error({
content: error.msg,
duration: 5 * 1000,
});
return Promise.reject(error);
}
);
依赖导入
在pom文件中添加对应的依赖
<!--用来处理POL相关的操作:easypol-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.2.0</version>
</dependency>
java重要代码
@GetMapping("/certificateCode")
public void certificateDownload(@RequestParam("pcid") String pcid,HttpServletResponse response)throws Exception{
JwtUser user = (JwtUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String code= IdUtil.fastSimpleUUID();
if(StringUtils.isNotBlank(pcid) && StringUtils.isNotBlank(code)){
String pdfPath="文件夹路径";
if(pdfPath!=null){
//压缩文件
if(FileToZip.fileToZip1(pdfPath, pdfPath, code)){
//下载文件
FileToZip.download(pdfPath+"/"+code+".zip",response);
}
//删除文件
FileToZip.deletefile(pdfPath);
}
}
}
@GetMapping("/scoreCode")
public void scoreDownload(@RequestParam("pcid") String pcid,HttpServletResponse response)throws Exception{
JwtUser user = (JwtUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String code= IdUtil.fastSimpleUUID();
List<ScoreVo> list= new ArrayList<>();
ScoreVo s=new ScoreVo();
s.setName("123456");
s.setNote("111111");
list.add(s);
try {
//导出操作
ExcelUtil.exportExcel(list,null,"sheet", ScoreVo.class,code+".xlsx",response);
} catch (Exception e) {
e.getMessage();
}
}
实体类ScoreVo
@Data
public class ScoreVo{
@Excel(name="姓名")
private String name;
@Excel(name="状态")
private String note;
}
Excel导入导出工具类
public class ExcelUtil {
/**
* 导出工具类
* @param list
* @param title
* @param sheetName
* @param pojoClass
* @param fileName
* @param isCreateHeader
* @param response
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,
String fileName, boolean isCreateHeader, HttpServletResponse response){
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* 导出工具类
* @param list
* @param title
* @param sheetName
* @param pojoClass
* @param fileName
* @param response
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,String fileName,
HttpServletResponse response){
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response){
defaultExport(list, fileName, response);
}
private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName,
HttpServletResponse response, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams,pojoClass,list);
if (workbook != null); downLoadExcel(fileName, response, workbook);
}
private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
try {
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(response.getOutputStream());
} catch (IOException e) {
//throw new NormalException(e.getMessage());
}
}
private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
if (workbook != null);
downLoadExcel(fileName, response, workbook);
}
public static <T> List<T> importExcel(String filePath,Integer titleRows,Integer headerRows, Class<T> pojoClass){
if (StringUtils.isBlank(filePath)){
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
}catch (NoSuchElementException e){
//throw new NormalException("模板不能为空");
} catch (Exception e) {
e.printStackTrace();
//throw new NormalException(e.getMessage());
} return list;
}
public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass){
if (file == null){ return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
}catch (NoSuchElementException e){
// throw new NormalException("excel文件不能为空");
} catch (Exception e) {
//throw new NormalException(e.getMessage());
System.out.println(e.getMessage());
}
return list;
}
}
压缩文件工具类 FileToZip.java
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public final class FileToZip {
private FileToZip(){}
/**
* 将存放在sourceFilePath目录下的源文件,打包成fileName名称的zip文件,并存放到zipFilePath路径下
* @param sourceFilePath :待压缩的文件路径
* @param zipFilePath :压缩后存放路径
* @param fileName :压缩后文件的名称
* @return
* @throws IOException
*/
public static boolean fileToZip(String sourceFilePath, String zipFilePath, String fileName) throws IOException {
boolean flag = false;
File sourceFile = new File(sourceFilePath);
if(sourceFile.exists() == false) {
System.out.println(">>>>>> 待压缩的文件目录:" + sourceFilePath + " 不存在. <<<<<<");
flag = false;
return flag;
} else {
try {
File zipFile = new File(zipFilePath + "/" + fileName + ".zip");
if(zipFile.exists()) {
System.out.println(">>>>>> " + zipFilePath + " 目录下存在名字为:" + fileName + ".zip" + " 打包文件. <<<<<<");
} else {
File[] sourceFiles = sourceFile.listFiles();
String[] filelist = sourceFile.list();
if(filelist.length<1){//二次开发2021-05-11 判断文件夹下面是否存在文件否文件夹
//if( null == sourceFiles || sourceFiles.length < 1) {
System.out.println(">>>>>> 待压缩的文件目录:" + sourceFilePath + " 里面不存在文件,无需压缩. <<<<<<");
flag = false;
return flag;
} else {
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile))); //用到时才申明,否则容易出现问题,记得先开后关,后开先关
byte[] bufs = new byte[1024*10]; //缓冲块
for(int i=0;i<sourceFiles.length;i++) {// 创建ZIP实体,并添加进压缩包
ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName());
zos.putNextEntry(zipEntry);// 读取待压缩的文件并写进压缩包里
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFiles[i]),1024*10); //用到时才申明,否则容易出现问题,记得先开后关,后开先关
int read = 0;
while((read=(bis.read(bufs, 0, 1024*10))) != -1) {
zos.write(bufs, 0, read);
}
if(null != bis) bis.close(); //关闭
}
flag = true;
if(null != zos) zos.close(); //关闭
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
return flag;
}
/***
* 下载文件
* @param path
* @param response
* @return
*/
public static void download(String path, HttpServletResponse response) {
try {
// path是指欲下载的文件的路径。
File file = new File(path);
// 取得文件名。
String filename = file.getName();
// 取得文件的后缀名。
String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
//支持中文名
filename = URLEncoder.encode(filename,"UTF-8");
// 以流的形式下载文件
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
response.addHeader("Content-Disposition", "attachment;filename=" +filename);
response.addHeader("Content-Length", "" + buffer.length);
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
response.setHeader("Access-Control-Allow-Origin", "*");//这个地方一定要设置,解决跨域问题,我在配置文件中加上跨域没有作用
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}
//return response;
}
/**
* 删除某个文件夹下的所有文件夹和文件
*
* @param delpath
* @throws FileNotFoundException IOException
* @return boolean
*/
public static boolean deletefile(String delpath) throws Exception {
File file = new File(delpath);
if (file.isDirectory()) {
String[] filelist = file.list();
for (String delFile : filelist) {
File delfile = new File(delpath + File.separator + delFile);
if (delfile.isDirectory()) {
deletefile(delpath + File.separator + delFile);
} else
System.out.println("正在删除文件:" + delfile.getPath() + ",删除是否成功:" + delfile.delete());
}
System.out.println("正在删除空文件夹:" + file.getPath() + ",删除是否成功:" + file.delete());
} else
System.out.println("正在删除文件:" + file.getPath() + ",删除是否成功:" + file.delete());
return true;
}
public static boolean fileToZip1(String sourceFilePath, String zipFilePath, String fileName) throws IOException {
boolean flag = false;
File sourceFile = new File(sourceFilePath);
if(sourceFile.exists() == false) {
System.out.println(">>>>>> 待压缩的文件目录:" + sourceFilePath + " 不存在. <<<<<<");
flag = false;
return flag;
} else {
try {
File zipFile = new File(zipFilePath + "/" + fileName + ".zip");
FileOutputStream fos1 = new FileOutputStream(zipFile);
toZip(fileName + ".zip",zipFilePath, fos1,true);
flag=true;
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
return flag;
}
/**
* 压缩成ZIP 方法1
* @param srcDir 压缩文件夹路径
* @param out 压缩文件输出流
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
*false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(String fileName, String srcDir, OutputStream out, boolean KeepDirStructure)
throws RuntimeException {
long start = System.currentTimeMillis();
ZipOutputStream zos = null ;
try {
zos = new ZipOutputStream(out);
File sourceFile = new File(srcDir);
compress(fileName,sourceFile,zos,sourceFile.getName(),KeepDirStructure);
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) +" ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils",e);
}finally{
if(zos != null){
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 递归压缩方法
* @param sourceFile 源文件
* @param zos zip输出流
* @param name 压缩后的名称
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws Exception
*/
private static void compress(String fileName, File sourceFile, ZipOutputStream zos, String name,
boolean KeepDirStructure) throws Exception {
byte[] buf = new byte[2 * 1024];
if(sourceFile.isFile()){
if(name.indexOf(fileName)==-1) {
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zos.putNextEntry(new ZipEntry(name));
// copy文件到zip输出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
}
} else {
File[] listFiles = sourceFile.listFiles();
if(listFiles == null || listFiles.length == 0){
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if(KeepDirStructure){
// 空文件夹的处理
zos.putNextEntry(new ZipEntry(name + "/"));
// 没有文件,不需要文件的copy
zos.closeEntry();
}
}else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (KeepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
compress(fileName,file, zos, name + "/" + file.getName(),KeepDirStructure);
} else {
compress(fileName,file, zos, file.getName(),KeepDirStructure);
}
}
}
}
}
}
vue 中main.js文件,如果有mock,一定要去掉,要不然会自动删除responseType类型