Translate

2019년 10월 30일 수요일

[jQuery] Ajax 이용한 파일 다운로드 (Chrome, Firefox, IE11 테스트완료)




이번에 jQuery를 사용하는 프로젝트를 사용하면서 Ajax 다운로드 라이브러리를 사용할까 하다가 그냥 공통파일에 구현을 했다.

크롬, 파이어폭스 익스플로러11 에서 정상적으로 동작하는것을 확인했다.
(2019.10.30)


다운로드 로직
1004lucifer
/**
 * 서버에 요청하여 파일을 다운로드 한다. (Chrome, Firefox, IE11 테스트 완료)
 * @param reqObj 요청정보 -  {
 *     url: 'url',          (required)
 *     method: 'GET|POST',  (optional - default:post)
 *     data: {              (optional)
 *         key1: value,
 *         key2: value
 *     }
 * }
 */
function requestDownloadFile(reqObj) {
    if (!reqObj || !reqObj.url) {
        return;
    }

    var isGetMethod = reqObj.method && reqObj.method.toUpperCase() === 'GET';
    $.ajax({
        url: reqObj.url,
        method: isGetMethod ? 'GET' : 'POST',
        xhrFields: {
            responseType: 'arraybuffer'
        },
        data: $.param(reqObj.data) // a=1&b=2&c=3 방식
        // data: JSON.stringify(reqObj.data) // {a:1, b:2, c:3} JSON 방식

    }).done(function(data, textStatus, jqXhr) {
        if (!data) {
            return;
        }
        try {
            var blob = new Blob([data], { type: jqXhr.getResponseHeader('content-type') });
            var fileName = getFileName(jqXhr.getResponseHeader('content-disposition'));
            fileName = decodeURI(fileName);

            if (window.navigator.msSaveOrOpenBlob) { // IE 10+
                window.navigator.msSaveOrOpenBlob(blob, fileName);
            } else { // not IE
                var link = document.createElement('a');
                var url = window.URL.createObjectURL(blob);
                link.href = url;
                link.target = '_self';
                if (fileName) link.download = fileName;
                document.body.append(link);
                link.click();
                link.remove();
                window.URL.revokeObjectURL(url);
            }
        } catch (e) {
            console.error(e)
        }
    });
}
function getFileName (contentDisposition) {
    var fileName = contentDisposition
        .split(';')
        .filter(function(ele) {
            return ele.indexOf('filename') > -1
        })
        .map(function(ele) {
            return ele
                .replace(/"/g, '')
                .split('=')[1]
        });
    return fileName[0] ? fileName[0] : null
}



해당 함수를 사용하는 코드
1004lucifer
/**
 * 다운로드 함수 사용방법
 */
requestDownloadFile({
    url: 'http://google.co.kr/download.do',
    method: 'POST',
    data: {
        a: 1,
        b: 2,
        c: 3
    }
});




참고
https://codepen.io/chrisdpratt/pen/RKxJNo?editors=1010


2019년 10월 23일 수요일

[Java] 파일 다운로드 시 파일명 한글 깨짐 방지 처리





최근 Java에서 파일 다운로드 할 시 한글이 깨지지 않게 작업하는데..
인터넷에 있는 대부분의 방법이 Firefox에서 한글이 깨져서 다운로드되었다.
(어떻게 파이어폭스에서 한글이 깨지지 않았는지 궁금하다)


결국 모질라사이트를 참고하여 한글, 특수문자 깨지지 않게 작업하여 다음과 같이 소스를 공유한다.
1004lucifer
다운로드 받는 파일명 깨지지 않게 하는게 포스팅의 주제라서 Spring Boot 로 간단히 예제를 만들어 봤고 GitHub 사이트에 소스를 올려놨다.
https://github.com/1004lucifer/Test_Java-download-filename
(해당소스 빌드 후 http://localhost:8080/downloadFile 접속 하여 테스트 할 수 있다.)

/**
 * @author 1004lucifer
 *
 * Test Date: 2019.10.23
 * Test Browser: IE11, Edge, Firefox(v70.0), Chrome(v77.0.3865.90)
 */
@RestController
public class DownloadKoreanFileName {

    @GetMapping("/downloadFile")
    public ResponseEntity<String> downloadFile(HttpServletRequest request) {

        String fileName = "abcd efg\t한글제목\t`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?.txt";
        String fileContent = "abcd efg\t한글내용\t`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?";

//        IE, Edge 여부 확인
        String browser = request.getHeader("User-Agent");
        boolean isMs = browser.contains("MSIE") || browser.contains("Trident");

//        파일명 인코딩
        fileName = URLEncoder.encode(fileName).replaceAll("\\+", "%20");
//        Firefox 에서 사용할 Rfc5987
        String filenameRfc5987 = "UTF-8''" + fileName;

//        content-disposition 헤더 설정
//        Firefox에서 filename* 항목을 설정해줘야 한글이 깨지지 않는다.
//        MS에서 filename* 항목 설정 시 파일명이 정상적으로 안나오고 기본값으로 나온다.
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        "attachment; filename=\"" + fileName + "\";" +
                                (isMs ? "" : "filename*=\"" + filenameRfc5987 + "\";"))
                .body(fileContent);
    }
}


1004lucifer
특수문자와 파이어폭스 관련 아래의 이슈도 참고를 할 필요가 있다.

링크 - [Chrome] 파일 다운로드 시 파일명 물결표(~) 표시가 언더바(_)로 변경되는 이슈
링크 - [Firefox] 파일 다운로드 시 한글깨짐 원인 및 수정방법




[Firefox] 파일 다운로드 시 한글깨짐 원인 및 수정방법





Java로 파일 다운로드 기능을 만들었는데 Firefox 에서만 한글이 깨져서 다운로드되어 이번에 원인과 수정방법을 알아보게 되었다.


다운로드되는 파일명을 결정하는 헤더인 Content-Disposition 에 대해서 모질라사이트(링크)에서 알아보니 filename* 라는 항목이 있었다.
1004lucifer
아래에 해당 내용의 일부를 긁어왔다.
filename* 라는 항목은 RFC5987에 정의된 인코딩을 사용할때 사용되며 filename 항목보다 우선한다고 한다.





filename
Is followed by a string containing the original name of the file transmitted. The filename is always optional and must not be used blindly by the application: path information should be stripped, and conversion to the server file system rules should be done. This parameter provides mostly indicative information. When used in combination with Content-Disposition: attachment, it is used as the default filename for an eventual "Save As" dialog presented to the user. 1004lucifer
filename*
The parameters "filename" and "filename*" differ only in that "filename*" uses the encoding defined in RFC 5987. When both "filename" and "filename*" are present in a single header field value, "filename*" is preferred over "filename" when both are understood.


따라서 abcd efg 한글제목 `~!@#$%^&*()-_=+[{]}\|;:'",<.>/?.txt 라는 이름의 파일을 다운로드 할 때 아래와 같이 filename* 항목을 추가하게되면 정상적으로 한글파일이 다운로드 되는것을 확인할 수 있다.
(파일명은 인코딩된 값이다.)
1004lucifer


attachment; filename="abcd%20efg%09%ED%95%9C%EA%B8%80%EC%A0%9C%EB%AA%A9%09%60%7E%21%40%23%24%25%5E%26*%28%29-_%3D%2B%5B%7B%5D%7D%5C%7C%3B%3A%27%22%2C%3C.%3E%2F%3F.txt";filename*="UTF-8''abcd%20efg%09%ED%95%9C%EA%B8%80%EC%A0%9C%EB%AA%A9%09%60%7E%21%40%23%24%25%5E%26*%28%29-_%3D%2B%5B%7B%5D%7D%5C%7C%3B%3A%27%22%2C%3C.%3E%2F%3F.txt";


PS.
위의 작업을 반영한 소스는 아래의 링크에서 확인이 가능하다.
링크 - [Java] 파일 다운로드 시 파일명 한글 깨짐 방지 처리



참고
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
https://tools.ietf.org/html/rfc5987



2019년 10월 22일 화요일

[Chrome] 파일 다운로드 시 파일명 물결표(~) 표시가 언더바(_)로 변경되는 이슈




증상
1004lucifer
파일명에 tilde(~) 표시가 있는경우 윈도우 크롬 브라우저에서 파일 다운로드시 '~' 글자가 '_' 로 변경되어 다운로드 되어진다.




원인
1004lucifer
2015년 chromium 에서 tilde(~) 글자의 파일명을 윈도우에서 지원하지 않도록 변경되었다.



참조
https://bugs.chromium.org/p/chromium/issues/detail?id=479419
https://chromium.googlesource.com/chromium/src/+/92a354fca8d118ad1be38612f85aa71a9a25303b


[IntelliJ] 라이센스 인증 시 오류 - SignatureException: Signature doesn't match or Signature length not correct: got 256 but was expecting 512




증상

라이센스가 만료되어 갱신을 하려 하는데 아래와 같이 에러가 발생하며 인증이 정상적으로 되지 않았다.


JetBrains Account connection error: java.security.SignatureException: Signature length not correct: got 128 but was expecting 512

1004lucifer




재부팅 후 IntelliJ 를 다시 구동해서 라이센스를 넣으니..
Proxy host 관련 에러메시지가 보여지고 나서야 원인을 알수가 있었다.






원인 및 해경방안

현재 내가 사용하는 인터넷망은 고객사의 네트워크에 붙어있는 상황이었다.
따라서 고객사 네트워크 어딘가에서 네트워크 변조가 일어나고 있는 것으로 예상이 된다.
1004lucifer
IntelliJ를 사용하다보면 아래와 같은 메시지 팝업이 주기적으로 열렸었다.
별생각없이 Accept 버튼을 누르고 넘어갔었는데 지금 생각해보니 고객사 네트워크를 사용할때만 저 팝업이 보여지고 있다.

일반 인터넷 네트워크로 접속 시 정상적으로 인증이 가능했다.


Untrusted Server's Certificate (Server's certificate is not trusted)



참고
https://intellij-support.jetbrains.com/hc/en-us/articles/206544889-SignatureException-Signature-doesn-t-match-or-Signature-length-not-correct-got-256-but-was-expecting-512