jQuery fileDownload로 구현된 파일다운로드 기능을 jQuery를 쓰지않고 axios를 사용도록 바꾸는 과정에서 에러가 발생했다.
1. 에러난 코드
controller (JAVA)
@ResponseBody
@RequestMapping(value = "/downloadExcel/", method = RequestMethod.POST)
public void exportComponentFile(HttpServletResponse response,
@RequestParam(value = "excelData") String excelData) {
//response.setHeader("Access-Control-Allow-Origin", "*");
try {
excelData = URLDecoder.decode(excelData, "UTF-8");
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> data = mapper.readValue(excelData, new TypeReference<HashMap<String, Object>>() {});
List<excelData> datas = mapper.readValue((String) data.get("excelData"), new TypeReference<List<excelData>>() {});
data.put("datas", datas);
String title = (String) data.get("title");
String rootPath = servletContext.getRealPath("/");
String templateFilePath = rootPath + "/WEB-INF/template/template.xlsx";
List<String> deleteFileList = new ArrayList<>();
File dir = new File(rootPath + "/WEB-INF/template/templateResult/");
if(!dir.exists()) {
dir.mkdir();
}
try (InputStream is = new FileInputStream(templateFilePath)) {
try (OutputStream os = new FileOutputStream(rootPath + "/WEB-INF/template/templateResult/" + title + ".xlsx")) {
Context context = new Context();
context.putVar("data", data);
Workbook workbook = WorkbookFactory.create(is);
workbook.setSheetName(0, functionId);
PoiTransformer transformer = PoiTransformer.createTransformer(workbook);
transformer.setOutputStream(os);
JxlsHelper.getInstance().processTemplate(context, transformer);
}
}
if(deleteFileList.size() > 1){
// zip 포맷
} else {
// 단일 파일
try (InputStream fis = new FileInputStream(rootPath + "/WEB-INF/template/templateResult/" + functionId + ".xlsx");
OutputStream outStream = response.getOutputStream()) {
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"",
java.net.URLEncoder.encode(functionId + ".xlsx", "UTF-8")));
response.setHeader("Set-Cookie", "fileDownload=true; path=/");
FileCopyUtils.copy(fis, outStream);
deleteFileList.add(title + ".xlsx");
}
}
File[] files = dir.listFiles();
for(File file : files){
file.delete();
}
dir.delete();
} catch (Exception e) {
logger.error("Exception: ", e);
}
}
jQuery fileDownload 사용 (기존 코드)
let excelData = {
title: title,
datas: JSON.stringify(datas),
};
var option = {
httpMethod: "POST",
data: {
excelData: encodeURIComponent(JSON.stringify(excelData)),
},
};
$.fileDownload(commonUtil.getDataServiceURL("downloadExcel"), option)
.done(function () {
console.log("success");
})
.fail(function () {
console.log("Fail");
});
axios 사용 (수정한 코드)
var option = {
params: { //여기가 꼭 params
httpMethod: 'POST',
excelData: '' //encodeURIComponent(JSON.stringify(excelData)),
// headers: {
// 'Access-Control-Allow-Origin': '*',
// 'Access-Control-Allow-Credentials': true
// }
}
};
const url = commonUtil.getDataServiceURL('downloadExcel');
axios
.post(url, null, option)
.then(response => {
console.log('success');
// 여기에서 다운로드된 파일을 처리할 수 있습니다.
const pom = document.createElement('a');
const absoluteUrl = result.path;
pom.setAttribute('href', absoluteUrl);
pom.setAttribute('download', excelData.title + '.zip');
pom.click();
})
.catch(error => {
console.log('fail');
});
excelData에 빈 스트링'' 또는 간단한 스트링'test'을 넘겼을 때는 컨트롤러 타는 것 까지 확인!!
excelData에 주석을 풀면 컨트롤러 까지 가지도 않고 아래 에러 발생함.
'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
2. 에러 해결
1. 'Access-Control-Allow-Origin': '*'
option에 주석처리한 부분을 'Access-Control-Allow-Origin': '*'를 추가해보고
자바에서도 response.setHeader("Access-Control-Allow-Origin", "*");를 추가해 봤는데 해결되지 않았다.
2. 데이터 길이의 문제
빈 스트링'' 또는 간단한 스트링'test'을 넘겼을 때는 컨트롤러로 넘어갔기 때문에 데이터의 문제인 것 같았다.
아래는 예전에 비슷한 경우에러.
form.submit을 썼기 때문에 그냥 긴 데이터를 제거하는 방법으로 해결했지만
이번에는 data 전송 방식을 달리하여 큰 size의 데이터를 전송해보았다.
브라우저는 URL의 길이에 대한 제한을 가지고 있을 수 있는데
axios.post() 메서드의 data 속성을 사용하여 데이터를 POST 요청의 본문(body)에 담아 전송하는 방법을 사용하여
긴 데이터를 보낼 수 있다.
const url = commonUtil.getDataServiceURL('excelDownlaod');
const data excelData: encodeURIComponent(JSON.stringify(excelData));
axios
.post(url, data, { responseType: 'blob' })
.then(response => {
console.log('success');
})
.catch(error => {
console.log('fail');
});
자바에서도 @RequestBody로 변경해야한다.
public void exportComponentFile(HttpServletResponse response,
@RequestBody String componentData) {}
참고로 RequestBody, RequestParam과 axios에서의 data, params 사용이 맞지 않으면 400에러가 난다.
*axios 데이터 전송 방법
*requestParam requestBody 차이
'error' 카테고리의 다른 글
whitelabel error page (0) | 2023.09.13 |
---|---|
[spring] Field required a bean of type that could not be found. (0) | 2023.08.30 |
form.submit / spring 전송 에러 (0) | 2022.12.13 |
chrome 106 drag and drop error (0) | 2022.10.13 |
_focusTabbable 에러 (0) | 2022.07.23 |