error

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.

dddzr 2023. 5. 25. 14:55

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'을 넘겼을 때는 컨트롤러로 넘어갔기 때문에 데이터의 문제인 것 같았다.

아래는 예전에 비슷한 경우에러.

https://sumni.tistory.com/77

 

form.submit / spring 전송 에러

form submit으로 spring controller에 요청을 보낼때 400에러가 발생함. "There was an unexpected error (type=Bad Request, status=400). Required String parameter 'parameter' is not present" 파라미터나 url을 잘 못 입력했을 때 나는

sumni.tistory.com

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 데이터 전송 방법

https://sumni.tistory.com/152

 

axios post 파라미터 전달 방법

axios.post() 메서드는 Axios 라이브러리를 사용하여 HTTP POST 요청을 보낼 때 사용되는 메서드입니다. axios.post(url[, data[, config]]) url: 요청을 보낼 URL 주소입니다. data (옵션): 요청의 본문에 담을 데이터

sumni.tistory.com

*requestParam requestBody 차이

https://sumni.tistory.com/153

 

@RequestParam @RequestBody 차이점

@RequestParam과 @RequestBody는 Spring Framework에서 요청 파라미터를 받는 데 사용되는 어노테이션입니다. @RequestParam 사용법: @RequestParam("paramName") 역할: URL 매개변수를 받아올 때 사용합니다. 예를 들어, ?

sumni.tistory.com

 

'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