2012-07-02 15 views
6

Kullanmakta olduğum eski bir kodum var (yani kodlanmış bir dosya adı bileşenine sahip bir URL kullanamıyorum). web sitemizden bir dosya indirin. Dosya adlarımız çoğu farklı dilde olduğu için hepsi UTF-8 olarak saklanır. RFC5987 dönüşümünü uygun bir dosya adı * parametresiyle işlemek için bazı kodlar yazdım. Bu, ascii olmayan karakterler ve boşlukları olan bir dosya adıma sahip olana kadar harika çalışıyor. RFC başına boşluk karakteri attr_char'ın bir parçası değildir, bu yüzden% 20 olarak kodlanır. Chrome’un yanı sıra Firefox’un yeni sürümlerine sahibim ve bunların hepsi indirme sırasında% 20'den + 'ya dönüşüyor. Alanı kodlamamayı ve kodlanmış dosya adını tırnak içine almayı denemedim ve aynı sonucu elde ettim. Servlet konteynerinin üstbilgilerimle eşleşmediğini doğrulamak için sunucudan gelen yanıtı kokladım ve bana doğru görünüyorlar. RFC bile% 20 içeren örneklere sahiptir. Bir şeyi özlüyorum mu, yoksa bu tarayıcıların hepsinin bununla ilgili bir sorunu var mı?dosya adıyla çalışma * RFC 5987 ile boşluk içeren parametreler, dosya adlarında '+' ile sonuçlanır

Şimdiden çok teşekkürler. Dosya adını kodlamak için kullandığım kod aşağıda. İşte 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(); 
} 

Güncelleme

benim açıklamada belirtildiği gibi boşluklu Çince karakterler ile bir dosya için olsun indirme diyalog bir ekran resmi. Julian Açıklamalarda belirttiği olarak

screen cap of download dialog

+0

bu soruna neden olan bir örnek başlığıdır: İçerik- Bırakma: eki; filename * = UTF-8''Museum% 20% 5A% 69% 86.jpg –

+0

Bkz. http://greenbytes.de/tech/tc2231/#attwithquotedsemicolon - bu test vakasının bir alıntı dizisinde boşluk karakteri var ve belirir. Firefox'ta çalışmak. Farklı şeyleri test ediyor muyuz? –

+0

Başka bir şeye benziyor. Bu test, alıntılanmış bir dizgede noktalı virgülü kontrol eder. Benim sorun, Çince karakterler yanı sıra boşluk ile bir dosya adı var, bu yüzden dosya adı * formu kullanıyorum ve% escapes ile tırnak kullanmayan bazı docs okuduğumdan belirteci tırnak formunda kullanıyorum. Yukarıdaki benim yorumumdan örnekle, Çince karakterler tanınıyor ve düzgün bir şekilde dönüştürülüyor, ancak% 20, + ile eşleştiriliyor. –

cevap

10

Yani, dolayısıyla bir çaylak Java hata yaptı ve bayt dönüştürme karakterime yapmak unuttum (böylece yerine karakterin bayt temsilinin karakterin codepoint kodlanmış) kodlama tamamen yanlıştı. Bu açıkça RFC 5987'de bir gereklilik olarak belirtilmiştir. Dönüşüm yapmak için düzeltilmiş kod yayınlayacağım. Kodlama doğru olduğunda, dosya adı * parametresi tarayıcı tarafından düzgün bir şekilde tanınır ve indirme için kullanılan dosya adı doğrudur.

Aşağıda, dizenin UTF-8 baytında çalışan düzeltilmiş çıkış kodu yer almaktadır. Bana şu anda sorun veren dosya adı şu şekilde görünüyor:

Content-Disposition: attachment; Dosya adı * = UTF-8''Museum% 20% E5% 8D% 9A% E7% 89,% A9% E9% A6% 86.jpg İşte

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

Bu karakteri '' 'rfc5987 izin verilen listesinde bulunmadığını belirtmek isterim. – Gedrox

+0

.. ama karakter '' '' '' '' '' '' '' '' '' '' '' '' '' '' \ '' '' '' '' '' '' '' '' '' '' '} Cevabı düzenlediniz. – Gedrox

İlgili konular