第一种写入流中返回
Response.setContentType(MIME)的作用是时客户端的浏览器区分不同种类的数据,并根据不同的MIME调用浏览器内不同的程序嵌入模块来处理相应的数据。
MIME-Version:
Content-Type:(常用。 该实体头的作用是让服务器告诉浏览器它发送的数据属于什么文件类型。)
Content-Transfer-Encoding:
Content-ID:
Content-Disposition: (常用。 当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。
原文链接:https://blog.csdn.net/u010405836/article/details/100767562
获取当前程序(或类文件)所在的目录可以用以下3个方法(可能还有其他方法,后续会逐步添加):
1、使用File类提供的方法来获取当前路径
2、使用Class类的getResource("").getPath()获取当前.class文件所在的路径
3、由System.getProperty("user.dir")获取当前程序的根目录
————————————————
版权声明:本文为CSDN博主「Asuka_08」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/AsuKA_F/article/details/94488884
文件预览
后端方法1
// todo 文件预览
@GetMapping(value = "/preview")
public void download(String filePath, HttpServletResponse response) throws Exception {
// 绝对路径 E:\code\experiment\back\formal\back-one
System.out.println(System.getProperty("user.dir"));
System.out.println(getClass().getResource("/"));
System.out.println(filePath);
// 读取的文件路径 filePath
FileInputStream in = null;
ServletOutputStream out = null;
in = new FileInputStream(filePath);
byte[] bytes = IOUtils.toByteArray(in);
response.setContentType("docx");
response.setContentLength(bytes.length);
response.setHeader("Content-Disposition", "attachment;filename=result");
out = response.getOutputStream();
out.write(bytes);
out.close();
in.close();
}
后端方法2
@GetMapping("/download")
@ResponseBody
public void downloadFile(HttpServletRequest request, HttpServletResponse response, String filePath) throws IOException {
String fileName = "result" + UUID.randomUUID().toString() + ".docx";// 设置文件名,根据业务需要替换成要下载的文件名
FileInputStream in = null;
ServletOutputStream out = null;
in = new FileInputStream(filePath);
response.setContentType("application/force-download");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);//设置文件名
out = response.getOutputStream();
IOUtils.copy(in,out);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
word文件预览插件vue实现
import {defaultOptions, renderAsync} from "docx-preview";
<el-dialog
id="container"
:visible.sync="wordDialogVisible"
>
</el-dialog>
<el-button @click="doTest">
回归测绘师
</el-button>
doTest() {
this.$axios({
url: 'http://localhost:40822/api/XXX/cluster/download',
method: 'get',
params: {filePath: this.word},
responseType: 'blob'
}).then(res => {
const blob = new Blob([res.data]);
this.wordDialogVisible = true;
renderAsync(blob, document.getElementById("container"))
})
},
###后端返回byte[]
@GetMapping(value = "/preview")
public byte[] preview(String filePath, HttpServletResponse response) throws Exception {
System.out.println(filePath);
// 读取的文件路径 filePath
FileInputStream in = null;
ServletOutputStream out = null;
in = new FileInputStream(filePath);
byte[] bytes = IOUtils.toByteArray(in);
response.setContentType("xlsx");
response.setContentLength(bytes.length);
response.setHeader("Content-Disposition", "attachment;filename=result");
return bytes;
}
前端下载 responseType: ‘arraybuffer’
//method方法:
handleExport() {
this.$axios({
url: 'http://localhost:40822/api/xjtu/multiRegression/preview',
method: 'get',
params: {filePath: this.excelPath},
responseType: 'arraybuffer'
}).then(res => {
var fileName = "ress"
const blob = new Blob([res.data]);
let a = document.createElement("a"); //创建一个标签
a.href = URL.createObjectURL(blob); // 将流文件写入a标签的href属性值
a.download = fileName + ".xlsx"; //设置文件名
a.style.display = "none"; // 障眼法藏起来a标签
document.body.appendChild(a); // 将a标签追加到文档对象中
a.click(); // 模拟点击了a标签,会触发a标签的href的读取,浏览器就会自动下载了
a.remove(); // 一次性的,用完就删除a标签
})
},
预览效果不理想,我想要有单元格的
第二 使用@GetMapping注解,指定返回格式
前端
import xlsx from "xlsx"
previewXlsx(){
this.$axios({
url: 'http://localhost:40822/api/xjtu/multiRegression/preview',
method: 'get',
params: {filePath: this.excelPath},
responseType: 'arraybuffer'
}).then(res => {
var fileName = "ress"
var XLSX = require("xlsx")
const blob = new Blob([res.data]);
let workbook =XLSX.read(new Uint8Array(res.data), { type: 'array' }); // 解析数据
var worksheet = workbook.Sheets[workbook.SheetNames[0]]; // workbook.SheetNames 下存的是该文件每个工作表名字,这里取出第一个工作表
this.tableHtml= XLSX.utils.sheet_to_html(worksheet); // 渲染
})
}
后端
// // todo 文件预览 excel
@GetMapping(value = "/preview")
public byte[] preview(String filePath, HttpServletResponse response) throws Exception {
System.out.println(filePath);
// 读取的文件路径 filePath
FileInputStream in = null;
ServletOutputStream out = null;
in = new FileInputStream(filePath);
byte[] bytes = IOUtils.toByteArray(in);
response.setContentType("xlsx");
response.setContentLength(bytes.length);
response.setHeader("Content-Disposition", "attachment;filename=result");
return bytes;
}
通过a标签的链接向后端服务发get请求,接收后端的文件流,非常简单:
<a :href='"http://localhost:40822/api/XXX/cluster/downloadA"' >下载模板</a>
另一种情况是创建,动态创建a标签:
<el-button id="download" @click="downloadFile">下载文件</el-button>
downloadFile(){
let a = document.createElement('a')
a.href = 'http://localhost:40822/api/XXX/cluster/downloadA'
a.click();
},
后端
@GetMapping("/downloadA")
@ResponseBody
public void downloadFileA(HttpServletResponse response) throws IOException {
String filePath = "D:\\data\\StatisticalAnalysis\\1\\2022-08-27\\output\\word.docx";
String fileName = "result" + UUID.randomUUID().toString() + ".docx";// 设置文件名,根据业务需要替换成要下载的文件名
FileInputStream in = null;
ServletOutputStream out = null;
in = new FileInputStream(filePath);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/force-download");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);//设置文件名
out = response.getOutputStream();
IOUtils.copy(in,out);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
我的路径参数含有地址,所以后端解析出错,
地址是:word: ‘D:\data\StatisticalAnalysis\1\2022-08-27\output\word.docx’,
java.lang.IllegalArgumentException: Invalid character found in the request target [/api/xjtu/cluster/downloadA?filePath=D:\data\StatisticalAnalysis\1\2022-08-27\output\word.docx]. The valid characters are defined in RFC 7230 and RFC 3986
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:490) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:261) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.AbstractProtocol C o n n e c t i o n H a n d l e r . p r o c e s s ( A b s t r a c t P r o t o c o l . j a v a : 888 ) [ t o m c a t − e m b e d − c o r e − 9.0.41. j a r : 9.0.41 ] a t o r g . a p a c h e . t o m c a t . u t i l . n e t . N i o E n d p o i n t ConnectionHandler.process(AbstractProtocol.java:888) [tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.tomcat.util.net.NioEndpoint ConnectionHandler.process(AbstractProtocol.java:888)[tomcat−embed−core−9.0.41.jar:9.0.41]atorg.apache.tomcat.util.net.NioEndpointSocketProcessor.doRun(NioEndpoint.java:1597) [tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.41.jar:9.0.41]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor W o r k e r . r u n ( T h r e a d P o o l E x e c u t o r . j a v a : 617 ) [ n a : 1.8. 0 1 31 ] a t o r g . a p a c h e . t o m c a t . u t i l . t h r e a d s . T a s k T h r e a d Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131] at org.apache.tomcat.util.threads.TaskThread Worker.run(ThreadPoolExecutor.java:617)[na:1.8.0131]atorg.apache.tomcat.util.threads.TaskThreadWrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.41.jar:9.0.41]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
<el-button size="mini" type="primary" icon="el-icon-download" @click="handleExport">导出</el-button>
data 数据
word: 'D:\\data\\StatisticalAnalysis\\1\\2022-08-27\\output\\word.docx',
//method方法:
handleExport() {
var elemIF = document.createElement('iframe')
elemIF.src = 'http://localhost:40822/api/xjtu/cluster/downloadA?filePath=' + this.word
elemIF.style.display = 'none'
document.body.appendChild(elemIF)
},
@GetMapping("/downloadA/{filePath}")
@ResponseBody
public void downloadFileA(HttpServletResponse response ,@PathVariable("filePath") String filePath) throws IOException {
System.out.println(filePath);
String fileName = "result" + UUID.randomUUID().toString() + ".docx";// 设置文件名,根据业务需要替换成要下载的文件名
FileInputStream in = null;
ServletOutputStream out = null;
in = new FileInputStream(filePath);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/force-download");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);//设置文件名
out = response.getOutputStream();
IOUtils.copy(in,out);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
前端向后端传递参数 data: {filePath: this.word},其中word: ‘D:\data\StatisticalAnalysis\1\2022-08-27\output\word.docx’,因为这个word是个路径含有\ - 这种符号,前端会对这些进行编码
需要使用 encodeuricomponent
https://www.cnblogs.com/webSnow/p/15307306.html