2012-07-02 13 views
6

Mam pewien kod źródłowy, którym się zajmuję (więc nie mogę po prostu użyć adresu URL z zakodowanym elementem nazwy pliku), który pozwala użytkownikowi na pobierz plik z naszej strony internetowej. Ponieważ nasze nazwy plików są często w wielu różnych językach, wszystkie są przechowywane jako UTF-8. Napisałem kod do obsługi konwersji RFC5987 na odpowiedni parametr * nazwy pliku. Działa to wspaniale, dopóki nie będę mieć nazw plików o spacje non-ascii i spacje. Według RFC znak spacji nie jest częścią attr_char, więc jest zakodowany jako% 20. Mam nowe wersje Chrome i Firefox, a wszystkie konwertują do% 20 na + przy pobieraniu. Próbowałem nie kodować przestrzeni i umieszczać zakodowaną nazwę pliku w cudzysłowie i uzyskać ten sam wynik. Powąchałem odpowiedź pochodzącą z serwera, aby sprawdzić, czy kontener serwletu nie był zaplombowany nagłówkami i wyglądają one poprawnie. Dokument RFC zawiera nawet przykłady zawierające% 20. Czy czegoś brakuje, czy też wszystkie te przeglądarki mają błąd związany z tym?przetwarzanie nazw plików * parametry ze spacjami za pośrednictwem RFC 5987 skutkują "+" w nazwach plików

Wielkie dzięki z góry. Kod służący do kodowania nazwy pliku znajduje się poniżej.

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(); 
} 

Aktualizacja

Oto zrzut ekranu z okna pobierania ja trafiam do pliku z chińskich znaków ze spacjami, jak wspomniałem w moim komentarzu.

screen cap of download dialog

+0

Oto przykładowy nagłówek, który jest przyczyną problemu: Content- Dyspozycja: przywiązanie; nazwa pliku * = UTF-8''Muzeum% 20% 5A% 69% 86.jpg –

+0

Zobacz http://greenbytes.de/tech/tc2231/#attwithquotedsemicolon - ten test ma znak spacji w cytowanym ciągu i pojawia się pracować w Firefoksie. Czy testujemy różne rzeczy? –

+0

To wygląda na coś innego. Ten test sprawdza średnik w cytowanym ciągu. Mój problem polega na tym, że mam nazwę pliku z chińskimi znakami, a także spacje, więc używam nazwy pliku * formularza, a w tokenie nie jest cytowana, ponieważ czytam niektóre dokumenty, które zalecały nieużywanie cudzysłowów z% escapes. Na przykładzie z mojego komentarza powyżej chińskie znaki są rozpoznawane i konwertowane poprawnie, ale% 20 jest mapowany na +. –

Odpowiedz

10

Tak jak Julian zauważył w komentarzach, zrobiłem rekrut błąd Java i zapomniałem zrobić mój charakter do konwersji bajtów (czyli ja zakodowane kodowy bohatera zamiast reprezentacji bohatera bajtów), stąd kodowanie było całkowicie niepoprawne. Jest to wyraźnie wymieniane jako wymaganie w RFC 5987. Będę publikował poprawiony kod do wykonywania konwersji. Gdy kodowanie jest poprawne, parametr nazwa pliku * jest poprawnie rozpoznawany przez przeglądarkę, a nazwa pliku użyta do pobrania jest poprawna.

Poniżej znajduje się poprawiony kod ucieczki, który działa na bajtach UTF-8 ciągu. Nazwa pliku, która dawała mi kłopoty, teraz poprawnie zakodowana wygląda następująco:

Treść - Uporządkowanie: załącznik; nazwa pliku * = 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

Chciałbym podkreślić, że znak '' 'nie znajduje się na liście dozwolonych plików rfc5987. – Gedrox

+0

.. ale znak '\' (symbol akcent grób, backtick) jest. Zmieniono odpowiedź. – Gedrox

Powiązane problemy