파일 이름 부패 파일 다운로드 (IE)
-
03-07-2019 - |
문제
간단한 파일 업로드 다운로드 메커니즘을 구현했습니다. 사용자가 파일 이름을 클릭하면 파일이 http 헤더로 다운로드됩니다.
HTTP/1.1 200 OK
Date: Tue, 30 Sep 2008 14:00:39 GMT
Server: Microsoft-IIS/6.0
Content-Disposition: attachment; filename=filename.doc;
Content-Type: application/octet-stream
Content-Length: 10754
또한 일본 파일 이름도 지원합니다. 그렇게하려면이 Java 메소드로 파일 이름을 인코딩합니다.
private String encodeFileName(String name) throws Exception{
String agent = request.getHeader("USER-AGENT");
if(agent != null && agent.indexOf("MSIE") != -1){ // is IE
StringBuffer res = new StringBuffer();
char[] chArr = name.toCharArray();
for(int j = 0; j < chArr.length; j++){
if(chArr[j] < 128){ // plain ASCII char
if (chArr[j] == '.' && j != name.lastIndexOf("."))
res.append("%2E");
else
res.append(chArr[j]);
}
else{ // non-ASCII char
byte[] byteArr = name.substring(j, j + 1).getBytes("UTF8");
for(int i = 0; i < byteArr.length; i++){
// byte must be converted to unsigned int
res.append("%").append(Integer.toHexString((byteArr[i]) & 0xFF));
}
}
}
return res.toString();
}
// Firefox/Mozilla
return MimeUtility.encodeText(name, "UTF8", "B");
}
누군가가 긴 파일 이름으로 잘 작동하지 않는다는 것을 알게 될 때까지 지금까지 잘 작동했습니다. 예를 들어: あああああああああああああああ2008.10.1あ.doc
. 단일 바이트 도트 중 하나를 단일 바이트 밑줄로 변경하거나 첫 번째 문자를 제거하면 괜찮습니다. 즉, 도트 문자의 길이와 URL 인코딩에 따라 다릅니다. 다음은 몇 가지 예입니다.
이것은 깨졌다 (あああああああああああああああ2008.10.1あ.doc
):
Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008%2E10%2E1%e3%81%82.doc;
이것은 괜찮습니다 (あああああああああああああああ2008_10.1あ.doc
):
Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008_10%2E1%e3%81%82.doc;
이것은 또한 괜찮습니다 (あああああああああああああああ2008.10.1あ.doc
):
Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008%2E10%2E1%e3%81%82.doc;
아무도 단서가 있습니까?
해결책
gmail은 파일 이름을 다소 다르게 탈출합니다. 파일 이름이 인용되고 (이중 인용물) 단일 바이트 기간은 URL 에스케이프가 아닙니다. 이런 식으로, 질문의 긴 파일 이름은 괜찮습니다.
Content-Disposition: attachment; filename="%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%822008.10.1%E3%81%82.doc"
그러나 파일 이름의 바이트 길이에 여전히 제한이 있습니다 (즉, 버그, 나는 가정). 따라서 파일 이름이 단일 바이트 문자로만 만들어 지더라도 파일 이름의 시작이 잘립니다. 제한은 약 160 바이트입니다.
다른 팁
위에서 언급 한 바와 같이, 내용화 및 유니 코드는 브라우저 스니핑없이 각각의 다른 헤더를 반환하지 않고 모든 메인 브라우저를 작동시키는 것이 불가능합니다.
내 해결책은 내용화 헤더를 완전히 피하고 Filename을 URL 끝에 추가하여 브라우저가 파일을 직접 가져오고 있다고 생각하도록 속이는 것입니다. 예를 들어
http://www.xyz.com/cgi-bin/dynamic.php/あああああああああああああああ2008.10.1あ.doc
빠른 리디렉션 헤더가 주문형으로 설정할 수 있지만 링크를 만들 때 파일 이름을 알고 있다고 가정합니다.
여기서 주요 문제는 IE가 관련 RFC를 지원하지 않는다는 것입니다. 여기서는 RFC2231입니다. 보다 포인터 및 테스트 사례. 또한, IE에 사용하는 해결 방법 (백분율 UTF-8을 사용하는 경우)에는 몇 가지 추가 문제가 있습니다. 모든 지역에서는 작동하지 않을 수 있습니다 (내가 기억하는 한, IE가 항상 기본값이 아닌 URL에서 UTF-8을 사용하도록 구성되지 않는 한, 한국에서는 방법이 실패합니다. 앞에서 언급했듯이 길이 제한이 있습니다 (I 그 말을 들어라 저것 IE8에 고정되어 있지만 아직 시도하지 않았습니다).
이 문제는 IE8에서 고정되어 있다고 생각합니다. IE 8에서 작동하는 것을 보았습니다.