目的:主要是实现一个前端选择某一个目录,js读取目录下所有文件,并上传到后端进行处理,处理完成之后把统计信息导出excel。
第一版:前端请求。结果是:能导出,但是文件数据乱码。网上一通搜索,处理结果要么没效果,要么后端收不到请求。搞了一天,快下班了找到另一种请求方式,见下文。
$.ajax({
url: '/damage/uploadimgList',
type: 'post',
async: false,
processData : false,
contentType : false,
data: data,
success: function (res) {
const blob = new Blob([res], {type:"application/vnd.ms-excel"});
if(blob.size < 1) {
alert('导出失败,导出的内容为空!');
return
if(window.navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, 'test.xls')
} else {
const aLink = document.createElement('a');
aLink.style.display = 'none';
aLink.href = window.URL.createObjectURL(blob);
aLink.download = 'test.xls';
document.body.appendChild(aLink);
aLink.click();
document.body.removeChild(aLink);
});
第二版:改成axios
<input type="file" id="selectFiles" onchange="dealSelectFiles()" webkitdirectory multiple>
读取目录下文件,转list,传到后台。
function dealSelectFiles(){
var selectFiles = document.getElementById("selectFiles").files;
var data = new FormData();
for (var i = 0; i < selectFiles.length; i++) {
data.append("files", selectFiles[i]);
axios.post("/damage/uploadimgList", data, {
responseType: 'blob'
}).then( function (res){
var filename = decodeURI(res.headers['content-disposition'].match(/(filename=(.*))/)[2])
var blob = new Blob([res.data], { type: "application/vnd.ms-excel" });
var objectUrl = URL.createObjectURL(blob);
var $a = $("<a>")
$a.attr("href", objectUrl)
$a.attr("download", filename)
$("body").append($a)
$a[0].click(0);
$a.remove()
}).catch(function (res) {
console.log(res)
return false;
最后也附上后端
@PostMapping("/uploadimgList")
public void uploadimgList(@RequestParam("files") List<MultipartFile> files, HttpServletResponse response) {
try {
List<DamageExcelVO> objects = demoService.uploadimgList(files);
response.setContentType("application/vnd.ms-excel");
String fileName = new String("残损统计.xlsx".getBytes(), StandardCharsets.ISO_8859_1);
response.setCharacterEncoding("utf8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
ServletOutputStream outputStream = response.getOutputStream();
EasyExcel.write(outputStream, DamageExcelVO.class).autoCloseStream(Boolean.FALSE).sheet("残损统计").doWrite(objects);
} catch (Exception e) {
e.printStackTrace();
【场景描述】
微服务架构中,使用前后端分离设计,用户点击导出下载Excel列表,通过AJAX与后端SpringMVC交互获取下载文件,请求需要携带Authorization认证信息,并且需要考虑到IE浏览器的兼容问题
【解决方案】
Ajax下载文件的这种方式本来就是禁止的。出于安全因素的考虑,javascript是不能够保存文件到本地的,
所以ajax考虑到了这点,只是接受json,text,html,xml格式的返回值,二进制的返回格式就会抛出这个异常。ajax请求只是个“字符型”的请求,即请求的内容是以
今天有一个导出相应数据为excel表的需求。后端的接口返回一个数据流,一开始我用axios(ajax类库)调用接口,返回成功状态200,但是!但是浏览器没有自动下载excel表,当时觉得可能是ajax的安全性问题导致无法下载。下面列觉两种我测试成功的方式:
1.window.location.href = ‘接口地址’
含义:当前页面打开URL页面.
和在浏览器输入接口地址一样,可以...
router.post("/downExcel", (req, res) => {
let assetsPath = path.resolve(__dirname, "../assets/1.xlsx");
res.set("Access-Control-Expose-Headers", "Content-Disposition");
(2)post请求, ‘application/x-www-form-urlencoded’,使用下面的方法或xhr原生
function exportData(api, params, encode) {
var form = $('<form>'); //定义一个form表
遇到的问题:
① 导出Excel,处理大量的数据
② 后端使用Apache POI中的SXSSFWorkbook导出功能,不使用xlsx.core.min.js前端导出考虑到前端导出的效率会比较低,需要多进处理一步数据
③ ajax处理文件流,这个应该不止可以用在导出excel文件,处理其他文件也是可以的
使用技术:HTML、CSS、JavaScript、SpringBoot
前端ajax部分代码逻辑:
* handlePrefix,ha
利用
ajax实现
excel报表
导出背景第一版主要代码测试结果第一版主要代码测试结果总结
项目中遇到一个场景,要
导出一个
excel报表。由于需要token验证,所以不能用a标签;由于页面复杂,所以不能使用表单提交。初步考虑
前端使用
ajax,
后端返回流,定义指定的header。
使用jquery的
ajax
var queryParams = {"test":"xxx"};
var url = "xxx";
$.
ajax({
type : "POST", //提交方式
通常情况下,导出Excel的后端接口会返回一个二进制流文件,前端需要通过ajax请求来获取该文件。在发送请求的时候,需要设置请求头部的Content-Type和responseType属性。
例如,使用jQuery发送ajax请求的代码如下:
```javascript
$.ajax({
url: 'your-api-url',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
responseType: 'arraybuffer',
success: function(response) {
// 处理响应数据
error: function(xhr, status, error) {
// 处理错误
其中,'Content-Type'设置为'application/json'是因为请求参数可能是JSON格式的;'Accept'设置为'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'是告诉后端接口返回Excel格式的文件。另外,responseType设置为'arraybuffer'是因为返回的数据是二进制流文件。
你需要根据你的后端接口返回的数据类型来设置Content-Type和Accept,一般情况下,后端会告诉你需要设置的请求头部信息。