Manipulando nomes de arquivos * com espaços através de RFC 5987 resulta em '+' em nomes de arquivos

Eu tenho um código legado com o qual estou lidando (então não, eu não posso simplesmente usar uma URL com um componente de nome de arquivo codificado) que permite ao usuário baixar um arquivo do nosso site. Como os nossos nomes de arquivos geralmente estão em vários idiomas diferentes, eles são armazenados como UTF-8. Eu escrevi algum código para lidar com a conversão RFC5987 para um parâmetro filename * adequado. Isso funciona muito bem até que eu tenha um nome de arquivo com caracteres não asciie espaços. Por RFC, o caractere de espaço não faz parte de attr_char, por isso, ele é codificado como% 20. Eu tenho novas versões do Chrome, bem como o Firefox e todos eles estão convertendo para% 20 para + no download. Eu tentei não codificar o espaço e colocar o nome do arquivo codificado entre aspas e obter o mesmo resultado. Eu cheirei a resposta vindo do servidor para verificar se o contêiner do servlet não estava mexendo com os meus cabeçalhos e eles parecem corretos para mim. O RFC ainda tem exemplos que contêm% 20. Estou faltando alguma coisa, ou todos esses navegadores têm um bug relacionado a isso?

Muito obrigado antecipadamente. O código que eu uso para codificar o nome do arquivo está abaixo.

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 = {'!','#','

Atualizar

Aqui está uma captura de tela da caixa de diálogo de download que recebo para um arquivo com caracteres chineses com espaços, conforme mencionado no meu comentário.

,'&','\'','+','-','.','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(); }

Atualizar

Aqui está uma captura de tela da caixa de diálogo de download que recebo para um arquivo com caracteres chineses com espaços, conforme mencionado no meu comentário.

questionAnswers(1)

yourAnswerToTheQuestion