FreeToGenerate.com

Monta os bytes exatos que um navegador manda ao enviar um arquivo, e também os lê. Nada é enviado: tudo acontece na sua aba.

Um campo de texto

Um campo de arquivo

Experimente um nome:

O delimitador entre as partes. Não pode aparecer dentro de nenhuma parte, e a especificação MIME limita a 70 caracteres.

O que acontece com os nomes

Nome do campocomo viaja
user
Nome do arquivocomo viaja
résumé (final).pdf
Dá para desfazer?
Sim: só este nome produz esses bytes
Tamanho do corpo
280

Um nome de arquivo fora do US-ASCII viaja como bytes UTF-8 crus, sem nada que anuncie isso, e por isso a contagem de bytes fica à frente da de caracteres.

Tudo isto roda no seu navegador. Nada é enviado.

Também disponível em: English · Español · Français · العربية

Gerador e analisador de multipart/form-data

Escreva a requisição que um navegador mandaria para enviar um arquivo, ou cole uma e descubra o que o servidor recebe de verdade.

O que é multipart/form-data

multipart/form-data é o formato que um navegador usa para mandar um formulário que contém um arquivo. Em vez de uma única string de pares chave-valor, o corpo é cortado em partes separadas por um delimitador chamado fronteira, e cada parte carrega os próprios cabeçalhos. Toda parte precisa declarar Content-Disposition: form-data com um parâmetro name dizendo de qual campo do formulário ela veio; a parte que representa um arquivo acrescenta um parâmetro filename e normalmente um Content-Type.

A fronteira é o único parâmetro obrigatório do Content-Type da requisição, porque sem ela o receptor não tem como saber onde uma parte termina e a próxima começa. Ela precisa ser uma string que não apareça dentro de nenhuma parte, e a especificação MIME limita a 70 caracteres. É por isso que navegadores de verdade geram algo longo e com cara de aleatório em vez de algo legível.

Dois detalhes do formato pegam as pessoas porque parecem ruído de formatação. As quebras de linha são pares CRLF e não quebras soltas, em todo lugar, inclusive na linha em branco que separa os cabeçalhos de uma parte do seu conteúdo. E o delimitador final leva dois hifens a mais no fim: é isso que diz que o corpo terminou em vez de ter sido cortado no caminho.

Como usar

  1. Escolha um modo. Montar uma requisição pega um campo de texto e um de arquivo e escreve os bytes que um navegador mandaria. Ler uma requisição pega um corpo que você já tem e deduz as partes que um servidor tira dele.
  2. No modo de montagem, digite o nome de arquivo que te interessa. Os botões de exemplo cobrem um nome simples, um com acentos, um que não pode ser recuperado e outro com aspas duplas. Repare na linha de baixo: ela mostra como cada nome viaja e se a transformação pode ser desfeita.
  3. No modo de leitura, cole o corpo e a fronteira. Você pode colar o cabeçalho Content-Type inteiro que a fronteira é extraída dele. A tabela lista cada parte que o servidor recebe; os achados abaixo se dividem em erros, que quebram alguma coisa; avisos, que significam que a requisição não foi montada por um navegador; e notas, que valem saber e não são falhas.

Três especificações, três respostas sobre o nome do arquivo

Pergunte como colocar um nome de arquivo fora do US-ASCII num envio e você recebe três respostas incompatíveis, todas normativas, e esta página existe porque a primeira que qualquer um usaria é explicitamente proibida.

A RFC 7578 resolve isso numa nota: a codificação da RFC 5987, que acrescentaria um parâmetro filename* ao cabeçalho Content-Disposition, não deve ser usada aqui. É exatamente o oposto da regra para um download. Numa resposta HTTP, a RFC 6266 exige filename* para qualquer nome que o US-ASCII não consiga expressar, e este site tem uma página separada sobre acertar isso. Mesmo cabeçalho, mesmo parâmetro, instrução oposta — e a única coisa que decide qual vale é se ele viaja numa resposta ou dentro do corpo de uma requisição.

A mesma seção então oferece uma segunda resposta: nomes de arquivo podem ser codificados com porcentagem, do jeito que uma URI file: seria codificada. E no parágrafo seguinte ela admite a terceira, que é o que realmente acontece: alguns sistemas amplamente implantados mandam nomes com octetos fora do US-ASCII diretamente, normalmente em UTF-8. Essa concessão merece ser lida duas vezes, porque uma especificação reconhecendo que o mundo faz outra coisa é uma especificação te dizendo o que o seu código vai receber.

O que os navegadores fazem é a terceira. O padrão HTML define o algoritmo que eles seguem, e ele manda o nome como bytes crus na codificação do formulário, sem nenhum parâmetro anunciando isso. Então um receptor que erre o palpite produz mojibake, e não há nada na requisição com que corrigir. O gerador aqui faz o que um navegador faz, e a linha abaixo mostra a contagem de bytes à frente da de caracteres, que é essa decisão tornada visível.

O escape não pode ser desfeito

O algoritmo do padrão HTML escapa exatamente três caracteres no nome de um campo ou de um arquivo: uma quebra de linha vira %0A, um retorno de carro vira %0D e aspas duplas viram %22. E aí ele fecha a lista com todas as letras: o agente de usuário não deve realizar nenhum outro escape.

Essa última frase é a interessante, porque significa que o sinal de porcentagem nunca é tocado. Um arquivo genuinamente chamado a%0Ab.txt e outro cujo nome contém uma quebra de linha real chegam os dois como a%0Ab.txt, e nada na requisição os distingue. O mesmo vale para %0D contra um retorno de carro e para %22 contra aspas duplas. Medido contra uma implementação real do algoritmo, não deduzido: os três pares saem idênticos.

Ou seja, a transformação é de mão única por projeto, e o conserto óbvio — escapar também a porcentagem — é justamente o que o padrão proíbe. Qualquer coisa que guarde um arquivo enviado com o nome que recebeu está assumindo em silêncio que isso nunca acontece. É raro, e não é impossível: uma porcentagem seguida de dois dígitos hexadecimais é exatamente a forma que um nome adquire depois de já ter passado por uma codificação de URL mais acima.

A ferramenta relata em vez de consertar, porque não há conserto a aplicar. Quando um nome divide os bytes com outro, a linha abaixo diz isso, e quem lê decide se aquilo importa para o que está construindo.

O que isto não vai te dizer

Isto lê o texto que você cola e nada mais. Um navegador não consegue inspecionar as requisições de outro site, então a ferramenta não faz ideia se o corpo que você está olhando é o que está sendo mandado, se o Content-Type ao lado dele combina, nem o que um servidor fez com ele depois.

O gerador escreve um corpo, não uma requisição. Ele mostra o cabeçalho Content-Type que precisa acompanhá-lo, porque é ali que a fronteira mora e sem ela o corpo não significa nada, mas o resto da requisição — o método, o caminho, o tamanho — é com você. Cole o corpo no cliente com que estiver testando em vez de esperar que isto mande alguma coisa.

Há uma simplificação deliberada. O conteúdo real de uma parte são bytes, e um navegador põe um JPEG numa parte sem cerimônia; isto trabalha em texto, então a parte de arquivo leva um marcador em vez de um arquivo de verdade. Todo o resto — a estrutura, os cabeçalhos, o escape e os delimitadores — é exatamente o que um navegador produz, e é disso que a página trata; mas não meça o tamanho de um envio real pelo que você vê aqui.

Por fim, o formato tem um mecanismo antigo que isto não implementa: Content-Transfer-Encoding, que um dia permitiu que uma parte fosse quoted-printable para sobreviver a um transporte de sete bits. A RFC 7578 diz aos emissores para não gerarem um sobre um transporte que carrega binário, e o HTTP carrega, então a ferramenta sinaliza se você colar um em vez de fingir que é normal.

Por que é grátis?

Montar e ler um corpo de requisição é trabalho de texto e roda no seu navegador. Não há servidor envolvido, então não há nada para cobrar nem conta para criar.

Nada é enviado e nada é guardado. Recarregue a página e ela terá esquecido o que você colou.