2012-07-02 21 views
6

Tôi có một số mã cũ mà tôi đang xử lý (vì vậy tôi không thể sử dụng URL có thành phần tên tệp được mã hóa) cho phép người dùng tải xuống tệp từ trang web của chúng tôi. Vì tên tệp của chúng tôi thường bằng nhiều ngôn ngữ khác nhau, tất cả đều được lưu trữ dưới dạng UTF-8. Tôi đã viết một số mã để xử lý việc chuyển đổi RFC5987 thành một tham số filename * thích hợp. Điều này hoạt động tốt cho đến khi tôi có tên tệp có ký tự không phải là ascii dấu cách. Mỗi RFC, ký tự khoảng trắng không phải là một phần của attr_char vì vậy nó được mã hóa dưới dạng% 20. Tôi có phiên bản Chrome mới cũng như Firefox và tất cả đều chuyển đổi thành% 20 thành + khi tải xuống. Tôi đã cố gắng không mã hóa không gian và đặt tên tập tin được mã hóa trong dấu ngoặc kép và nhận được kết quả tương tự. Tôi đã đánh hơi câu trả lời đến từ máy chủ để xác minh rằng thùng chứa servlet không bị nhòe với các tiêu đề của tôi và chúng trông đúng với tôi. RFC thậm chí có các ví dụ chứa% 20. Tôi có thiếu một cái gì đó, hoặc làm tất cả các trình duyệt có một lỗi liên quan đến điều này?xử lý tên tệp * tham số với dấu cách thông qua kết quả RFC 5987 trong '+' trong tên tệp

Rất cám ơn trước. Mã tôi sử dụng để mã hóa tên tệp dưới đây.

Peter

public static boolean bcsrch(final char[] chars, final char c) { 
    final int len = chars.length; 
    int base = 0; 
    int last = len - 1; /* Last element in table */ 
    int p; 

    while (last >= base) { 
     p = base + ((last - base) >> 1); 

     if (c == chars[p]) 
      return true; /* Key found */ 
     else if (c < chars[p]) 
      last = p - 1; 
     else 
      base = p + 1; 
    } 

    return false; /* Key not found */ 
} 

public static String rfc5987_encode(final String s) { 
    final int len = s.length(); 
    final StringBuilder sb = new StringBuilder(len << 1); 
    final char[] digits = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 
    final char[] attr_char = {'!','#','$','&','\'','+','-','.','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','^','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','|', '~'}; 
    for (int i = 0; i < len; ++i) { 
     final char c = s.charAt(i); 
     if (bcsrch(attr_char, c)) 
      sb.append(c); 
     else { 
      final char[] encoded = {'%', 0, 0}; 
      encoded[1] = digits[0x0f & (c >>> 4)]; 
      encoded[2] = digits[c & 0x0f]; 
      sb.append(encoded); 
     } 
    } 

    return sb.toString(); 
} 

Cập nhật

Đây là một ảnh chụp màn hình của hộp thoại tải về tôi nhận được cho một tập tin với các nhân vật Trung Quốc với các không gian như đã đề cập trong nhận xét của tôi.

screen cap of download dialog

+0

Đây là tiêu đề mẫu gây ra vấn đề này: Nội dung- Bố trí: tệp đính kèm; tên tệp * = UTF-8''Museum% 20% 5A% 69% 86.jpg –

+0

Xem http://greenbytes.de/tech/tc2231/#attwithquotedsemicolon - trường hợp thử nghiệm đó có ký tự khoảng trắng trong chuỗi trích dẫn và xuất hiện để làm việc trong Firefox. Chúng ta có thử nghiệm những thứ khác nhau không? –

+0

Trông giống như thứ khác. Kiểm tra đó kiểm tra dấu chấm phẩy trong một chuỗi trích dẫn. Vấn đề của tôi là tôi có một tên tập tin với các ký tự Trung Quốc cũng như dấu cách, vì vậy tôi đang sử dụng tên * biểu mẫu, và dưới dạng không được trích dẫn vì tôi đọc một số tài liệu không khuyến khích sử dụng dấu ngoặc kép với% escape. Với ví dụ từ nhận xét của tôi ở trên, các ký tự Trung Quốc được nhận dạng và chuyển đổi đúng cách, nhưng% 20 đang được ánh xạ tới +. –

Trả lời

10

Vì vậy, khi Julian chỉ ra trong các ý kiến, tôi đã thực hiện một tân binh lỗi Java và quên để làm nhân vật của tôi để chuyển đổi byte (như vậy, tôi mã hóa điểm mã của nhân vật thay vì đại diện byte của nhân vật), vì thế mà mã hóa hoàn toàn không chính xác. Điều này được đề cập rõ ràng là một yêu cầu trong RFC 5987. Tôi sẽ đăng mã được sửa chữa để thực hiện chuyển đổi. Khi mã hóa đúng, tham số filename * được trình duyệt nhận dạng đúng và tên tệp được sử dụng để tải xuống là chính xác.

Dưới đây là mã thoát được sửa chữa hoạt động trên byte UTF-8 của chuỗi. Tên tệp đã khiến tôi gặp sự cố, hiện được mã hóa chính xác như sau:

Nội dung-Bố trí: tệp đính kèm; tên tệp * = UTF-8''Museum% 20% E5% 8D% 9A% E7% 89% A9% E9% A6% 86.jpg

public static String rfc5987_encode(final String s) throws UnsupportedEncodingException { 
    final byte[] s_bytes = s.getBytes("UTF-8"); 
    final int len = s_bytes.length; 
    final StringBuilder sb = new StringBuilder(len << 1); 
    final char[] digits = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 
    final byte[] attr_char = {'!','#','$','&','+','-','.','0','1','2','3','4','5','6','7','8','9',   'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','^','_','`',      'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','|', '~'}; 
    for (int i = 0; i < len; ++i) { 
     final byte b = s_bytes[i]; 
     if (Arrays.binarySearch(attr_char, b) >= 0) 
      sb.append((char) b); 
     else { 
      sb.append('%'); 
      sb.append(digits[0x0f & (b >>> 4)]); 
      sb.append(digits[b & 0x0f]); 
     } 
    } 

    return sb.toString(); 
} 
+0

Muốn chỉ ra rằng ký tự ''' không có trong danh sách được phép của rfc5987. – Gedrox

+0

.. nhưng ký tự '\' '(biểu tượng dấu trọng âm, dấu gạch chéo ngược) là. Đã chỉnh sửa câu trả lời. – Gedrox

Các vấn đề liên quan