2011-01-19 5 views
6

Làm thế nào tôi có thể đặt tên tập tin được bản địa hoá trong java. Hiện tại, tôi nhấp vào một tệp đã được bản địa hóa có tên tệp không phải ascii trong ứng dụng của tôi, hộp thoại cửa sổ lưu bật lên, nhưng không hiển thị tên tệp đúng nếu bộ ký tự là bất kỳ thứ gì bên trên ISO-88859-1.Tên tập tin được bản địa hóa Java

Đây là mã của tôi đang lưu tệp.

  InputStream inputStream = null; 
try { 
    response.resetBuffer(); 
    response.setContentType(fileStream.getContentType()); 
    response.setContentLength((int) fileStream.getContentLength()); 
    response.addHeader("Content-Disposition", 
    "attachment;filename=\"" + fileName + "\""); 
    ServletOutputStream stream = response.getOutputStream(); 
    byte[] buffer = new byte[1024]; 
    int read = 0; 
    int total = 0; 
    inputStream = fileStream.getInputStream(); 
    while ((read = inputStream.read(buffer)) > 0) { 
    stream.write(buffer, 0, read); 
    total += read; 
    } 
    response.flushBuffer(); 
} finally { 
    if (inputStream != null) { 
    inputStream.close(); 
    } 
} 

Tôi sẽ rất hữu ích nếu ai đó có thể chia sẻ ý tưởng của họ về cách giải quyết vấn đề này. Cảm ơn trước.

Trả lời

13

Gustafc nói chính xác, nhưng nó không đưa bạn đến nơi bạn muốn. RFC 2231 cho phép bạn sử dụng định dạng thay thế cho các tham số không phải là ASCII Content-TypeContent-Disposition, nhưng không phải tất cả các trình duyệt đều hỗ trợ định dạng này. Cách đó là nhiều khả năng để làm việc, không may, là để bỏ qua những gì RFC 2183 nói và sử dụng RFC 2047 encoded-words trong phản ứng:

response.addHeader("Content-Disposition", "attachment; " + 
    "filename=\"" + MimeUtility.encodeWord(fileName, "utf-8", "Q") + "\""); 

Lưu ý rằng điều này có thể không làm việc cho tất cả các trình duyệt. Một số biến thể của IE yêu cầu bạn URL-mã hóa các giá trị thay vì:

response.addHeader("Content-Disposition", 
    "attachment; filename=" + URLEncoder.encode(filename, "utf-8")); 
+0

DKarp, Mã này thực sự hữu ích. Bây giờ tôi có thể nhận được kết quả mong muốn trên tất cả các trình duyệt khác ngoài IE. Với IE trong khi tải xuống tệp, nó sẽ mã hóa tên tệp để hiển thị ở định dạng thích hợp nhưng nó thêm toàn bộ URL vào nó và khi tôi cố gắng tải xuống tệp .xls, nó sẽ hiển thị hộp tiến trình tải xuống với cảnh báo trên đó có nội dung là "Internet Explorer không thể mở trang web này. Trang web không khả dụng hoặc không thể tìm thấy. " Tôi một lần nữa muốn bạn chỉ cho tôi đi đúng hướng. Cảm ơn sự giúp đỡ của bạn. – Hitatichi

+0

Mã bạn đang sử dụng để đặt tiêu đề 'Nội dung-Bố cục 'cho IE là gì? Tôi nghĩ rằng một số phiên bản của IE có thể không xử lý tốt với tiêu đề gấp, do đó hãy chắc chắn không đặt thêm một dòng mới trong tiêu đề ... – dkarp

+0

Tôi đã sử dụng URLEncoder cho IE chính xác như bạn đã chỉ định trong câu trả lời. response.addHeader ("Content-Disposition", "tệp đính kèm; filename =" + URLEncoder.encode (tên tệp "utf-8")); – Hitatichi

2

Từ section 2.3 in the spec, có vẻ như bạn không thể sử dụng các ký tự không US-ASCII:

hiện [RFC 2045] ngữ pháp hạn chế giá trị tham số (và do đó tên tập Content-Disposition) để US-ASCII. Chúng tôi nhận thấy sự tuyệt vời của việc cho phép các bộ ký tự tùy ý trong tên tệp, nhưng nó nằm ngoài phạm vi của tài liệu này để xác định các cơ chế cần thiết. Chúng tôi hy vọng rằng thông số cơ bản [RFC 1521] `giá trị ' một ngày nào đó sẽ được sửa đổi để cho phép sử dụng các ký tự không phải US-ASCII , tại thời điểm đó nên sử dụng cùng một cơ chế trong thông số tên tệp Nội dung-Bố trí.

+0

này là chính xác, nhưng vô ích. :) – dkarp

+0

Gustafc, Cảm ơn thời gian của bạn và RFC đã xác định lý do cho những kết quả không mong muốn này. – Hitatichi

4

tôi phải đối mặt với vấn đề tương tự với tên tập tin chứa greek characters.I sử dụng mã được cung cấp trong các câu trả lời trên (nhờ tôi để dkarp) kết hợp với phát hiện đó trình duyệt được sử dụng. đây là kết quả:

 
String user_agent = request.getHeader("user-agent"); 
boolean isInternetExplorer = (user_agent.indexOf("MSIE") > -1); 
if (isInternetExplorer) { 
    response.setHeader("Content-disposition", "attachment; filename=\"" + URLEncoder.encode(filename, "utf-8") + "\""); 
} else { 
    response.setHeader("Content-disposition", "attachment; filename=\"" + MimeUtility.encodeWord(filename) + "\""); 
} 

Tôi đã thử nghiệm nó bằng firefox 3.6, chrome 10.0 và Internet Explorer 8 và có vẻ hoạt động tốt.

1

Mặc dù câu hỏi cũ, nó vẫn còn thực tế. Tôi đã tìm thấy giải pháp phù hợp với tất cả các trình duyệt của mình.

Xem bài của tôi trong chủ đề khác:
Java servlet download filename special characters

Nói tóm lại, các trình duyệt hy vọng rằng giá trị trong filename tham số được mã hóa trong các trình duyệt mã nguồn gốc (nếu không có charset khác nhau được quy định cho filename tham số). Mã hóa gốc của trình duyệt thường là utf-8 (FF, Opera, Chrome), nhưng đối với IE, nó là win-1250. Do đó, nếu chúng ta đặt giá trị vào filename parametr, được mã hóa bởi utf-8/win-1250 theo trình duyệt của người dùng, nó sẽ hoạt động.

Ví dụ, nếu chúng ta có file có tên omáčka.xml,
cho FireFox, Opera và Chrome tôi phản ứng tiêu đề này (UTF-8):

Content-Disposition: attachment; filename="omáčka.xml" 

và cho IE tôi phản ứng tiêu đề này (được mã hóa trong win-1250):

Content-Disposition: attachment; filename="omáèka.jpg" 

Ví dụ Java là in my post được đề cập ở trên.

Lưu ý # 1 (@dkarp):

Hãy nhận biết của việc sử dụng URLEncoder.encode() vì phương thức này không mã hóa chuỗi nhập vào url-mã hóa. Phương thức này mã hóa các chuỗi đầu vào thành dạng mã hóa rất giống nhau nhưng khác trong một số trường hợp - ví dụ ký tự dấu cách '' được mã hóa thành '+' thay vì '% 20'.

Thực hiện mã hóa url chính xác bạn chứ không nên sử dụng URI lớp:

URI uri = new URI(null, null, "foo-ä-€.html", null); 
System.out.println(uri.toASCIIString());