Principais pontos
- Arquivos incluídos na requisição multipart de criação da Assembly não podem ser retomados, então qualquer interrupção faz a Assembly inteira falhar.
- Fazer upload via tus permite que o cliente continue a partir do offset de bytes que o servidor já tem, em vez de começar de novo.
- Crie primeiro a Assembly com num_expected_upload_files e depois faça upload dos arquivos para o endereço tus_url que ela retorna.
Uploads grandes não são requisições que falham de vez em quando. São transferências que serão interrompidas, e a verdadeira decisão se resume a saber se a interrupção vai custar ao usuário os bytes restantes ou todos eles. Todo o resto do design decorre dessa escolha.
O que mais importa
- Depois que a quantidade declarada tiver chegado, a Assembly deixa de esperar por uploads adicionais. Concilie a lista de uploads dela com os arquivos que você pretendia enviar.
- Os arquivos podem ter até 200 GB, mas, por padrão, os uploads precisam terminar em até oito horas após a criação da Assembly; o processamento tem um prazo separado.
Dois caminhos de upload, e apenas um deles pode ser retomado
A Transloadit aceita arquivos de duas formas, e a diferença entre elas só aparece em uma conexão ruim. Os arquivos podem ser anexados ao POST multipart/form-data que cria a Assembly, o que é simples e funciona bem para uma foto de perfil. Qualquer interrupção nessa requisição faz o upload falhar, e a Assembly junto com ele, e o cliente não tem como continuar: só pode enviar tudo de novo.
O outro caminho usa o tus, um protocolo aberto para uploads retomáveis via HTTP, com implementações de cliente na maioria das linguagens. A Transloadit executa um servidor tus, e um cliente que fala o protocolo pode pausar, perder a conexão e continuar a partir do último byte confirmado pelo servidor. Para qualquer coisa medida em centenas de megabytes, essa é a diferença entre um upload que acaba sendo concluído e um que nunca termina.
Multipart
Uma única requisição que leva os arquivos. Uma interrupção faz falhar tanto o upload quanto a Assembly.
tus
Uma transferência separada por arquivo, que pode ser continuada a partir do último byte confirmado.
Já resolvido para você
O Uppy e os SDKs de back-end usam tus por baixo, então a maioria das integrações já conta com isso sem trabalho extra.
Declare quantos arquivos virão
Um upload retomável inverte a ordem habitual: a Assembly é criada antes de existir qualquer byte. A requisição de criação leva params normalmente, além de um campo num_expected_upload_files que informa quantos arquivos virão em seguida, e nenhum conteúdo de arquivo. A resposta é um Assembly Status comum com dois acréscimos que importam aqui: tus_url, que indica para onde vão os uploads, e o trio expected_tus_uploads, started_tus_uploads e finished_tus_uploads, para acompanhá-los.
A Assembly permanece em ASSEMBLY_UPLOADING até que os uploads esperados tenham terminado, mesmo quando arquivos que chegaram antes já foram processados. Depois que a quantidade declarada tiver chegado, ela deixa de esperar por arquivos adicionais. Uploads atrasados podem ser rejeitados ou ignorados, dependendo do estado da Assembly, então defina a quantidade exata pretendida e concilie a lista final uploads com os arquivos que você pretendia enviar.
POST /assemblies HTTP/1.1
Host: api2.transloadit.com
Content-Type: multipart/form-data; boundary=---xyz
-----xyz
Content-Disposition: form-data; name="params"
{"auth":{"key":"YOUR_KEY"},
"template_id":"YOUR_TEMPLATE_ID"}
-----xyz
Content-Disposition: form-data;
name="num_expected_upload_files"
2
-----xyz--num_expected_upload_files
Defina-o como o número exato de arquivos que o cliente vai enviar e conte os arquivos antes de criar a Assembly.
tus_url
O endpoint de upload desta Assembly, retornado no Assembly Status em vez de fixo no código.
Reconciliar os arquivos recebidos
Compare a lista de uploads da Assembly com os arquivos pretendidos, em vez de presumir que uma conclusão bem-sucedida prova que todos os arquivos chegaram.
A retomada é um offset, não uma nova tentativa
Cada upload começa com um POST para tus_url que cria um recurso em vez de enviar dados. A requisição carrega três metadados, assembly_url, filename e fieldname, e o servidor responde com uma URL de upload no cabeçalho Location. Em seguida, os bytes vão para essa URL em uma ou mais requisições PATCH e, assim que a última chega, o arquivo é encaminhado para a Assembly sem nenhuma chamada adicional.
A recuperação usa a mesma URL. Uma requisição HEAD retorna um cabeçalho Upload-Offset com o número de bytes que o servidor realmente tem, e o cliente retoma com um PATCH que começa exatamente nesse offset. É por isso que uma nova tentativa e uma retomada não são a mesma operação: uma nova tentativa envia o arquivo de novo desde o zero, enquanto uma retomada pergunta ao servidor o que ele já tem e envia apenas a diferença.
HEAD /resumable/files/136058f2ef4d HTTP/1.1
Host: api2-freja.transloadit.com
Tus-Resumable: 1.0.0
HTTP/1.1 204 No Content
Upload-Offset: 3000
Upload-Length: 10000
PATCH /resumable/files/136058f2ef4d HTTP/1.1
Host: api2-freja.transloadit.com
Tus-Resumable: 1.0.0
Upload-Offset: 3000
Content-Length: 7000
Content-Type: application/offset+octet-streamCriar e depois transferir
O primeiro POST estabelece a URL de upload; as requisições PATCH carregam o conteúdo em si.
Upload-Offset
O servidor informa quanto recebeu, então o cliente nunca precisa adivinhar de onde continuar.
Guardar a URL de upload
Retomar depois de recarregar a página exige essa URL, então persista-a em vez de mantê-la na memória.
A transferência é retomada, mas a Assembly ainda expira
A capacidade de retomada costuma ser interpretada como um prazo de tolerância ilimitado, mas não é. Por padrão, o upload fica limitado a oito horas a partir da criação da Assembly, e o processamento, a oito horas a partir da conclusão do upload. Um limite de processamento específico do Workspace pode alterar a segunda janela. Uma Assembly que ultrapassa o prazo aplicável retorna ASSEMBLY_EXPIRED, e o upload parcial por trás dela deixa de ser útil.
Isso pesa mais justamente nas cargas de trabalho que mais precisam de retomada. Um usuário que pausa um upload grande durante a noite vai voltar para uma Assembly que não existe mais, então o cliente precisa detectar esse caso e criar uma nova em vez de tentar de novo em uma URL morta. Tratar a expiração como um resultado esperado, e não como um erro a ser registrado em log, mantém esse caminho de recuperação fiel à realidade.
Oito horas para o upload
Contado a partir da criação da Assembly, não do momento em que a transferência avançou pela última vez.
Prazo de processamento separado
A janela de processamento padrão é de oito horas a partir da conclusão do upload, separada do prazo de upload.
Planejar um reinício
Detecte uma Assembly expirada e crie uma nova em vez de tentar de novo a antiga URL de upload.
Anexe os metadados de que cada arquivo precisa
Além dos três valores obrigatórios, quaisquer metadados adicionais enviados com um upload ficam disponíveis como Assembly Variable em file.user_meta, de modo que uma chave enviada como owner é lida como ${file.user_meta.owner}. Vale a pena assimilar essa distinção cedo, porque fields é compartilhado por todos os arquivos da Assembly, enquanto os metadados enviados com cada upload pertencem a um único arquivo. Um lote em que cada arquivo precisa do próprio caminho de destino, proprietário ou categoria pede esses metadados por upload, e tentar expressar isso por campos compartilhados termina em um Template que não consegue distinguir os arquivos.
Para ramificar com base no conteúdo, e não no que o cliente declarou, prefira ${file.mime} e faça a correspondência com famílias como image/* ou video/*. Um nome de arquivo ou uma categoria fornecidos pelo cliente são apenas uma pista, e tratá-los como fato é o que faz um executável acabar em um caminho que presumia imagens. A categoria ampla ${file.type} também existe, mas a correspondência por MIME é a mais precisa das duas.
Os três obrigatórios
Todo upload precisa de assembly_url, filename e fieldname nos seus metadados tus.
Por arquivo ou por Assembly
Os metadados enviados com cada upload pertencem a um único arquivo; os campos são compartilhados por todos os arquivos na mesma execução.
Ramificar pelo MIME
Faça a correspondência com ${file.mime} em vez de confiar em uma extensão ou em uma categoria fornecida pelo cliente.
Assine a requisição quando o navegador for o cliente
Quando um upload começa em um navegador, as Assembly Instructions estão sendo enviadas de um ambiente que você não controla. A Signature Authentication fecha essa brecha: seu back-end assina os params com o Auth Secret, adiciona um timestamp auth.expires em um futuro próximo e entrega o resultado ao front-end. Ativar essa exigência nas Configurações do Workspace faz a API rejeitar qualquer requisição não assinada da conta.
A parte útil é que seu servidor decide o que está disposto a assinar. Ele pode recusar usuários anônimos, restringir o Template que uma requisição pode invocar ou limitar os parâmetros antes de assinar, tudo com lógica de aplicação comum. O Auth Secret nunca sai do back-end, e uma assinatura interceptada só vale até a expiração com que foi emitida.
const uppy = new Uppy().use(Transloadit, {
waitForEncoding: true,
assemblyOptions: async () => {
// Your back end signs with the Auth Secret
const res = await fetch('/api/tl-signature', { method: 'POST' })
if (!res.ok) throw new Error('Unable to authorize the upload')
const { params, signature } = await res.json()
return { params, signature }
},
})Assinar no servidor
O Auth Secret fica no back-end e nunca chega a um bundle do navegador.
auth.expires
Um timestamp em um futuro próximo que limita por quanto tempo uma assinatura emitida continua utilizável.
Exigir a assinatura
As Configurações do Workspace podem rejeitar de imediato toda requisição não assinada da conta.
Detalhes técnicos que vale a pena conhecer
- A Assembly é criada por um POST multipart que carrega params e num_expected_upload_files, mas nenhum conteúdo de arquivo, e a resposta inclui tus_url, expected_tus_uploads, started_tus_uploads e finished_tus_uploads.
- Uma Assembly permanece no estado ASSEMBLY_UPLOADING até que todos os uploads tus declarados tenham terminado, mesmo que alguns dos arquivos que ela já recebeu tenham sido processados.
- Cada upload tus começa com um POST para tus_url que leva assembly_url, filename e fieldname como metadados, e o servidor responde com a URL do upload no cabeçalho Location.
- Retomar consiste em uma requisição HEAD para essa URL de upload, que informa a quantidade de bytes recebidos no cabeçalho Upload-Offset, seguida de um PATCH que envia o restante exatamente a partir desse offset.
- Metadados extras enviados com um upload se tornam uma Assembly Variable em file.user_meta, que é por arquivo, ao contrário de fields, que é compartilhado por todos os arquivos da mesma Assembly.
- Por padrão, o upload é limitado a oito horas a partir da criação, e o processamento, a oito horas a partir da conclusão do upload. Um limite de processamento específico do Workspace pode alterar esse segundo prazo; ultrapassar qualquer um dos prazos retorna ASSEMBLY_EXPIRED.
Uma abordagem prática
- 1
Crie a Assembly com num_expected_upload_files definido como o número exato de arquivos que o cliente vai enviar.
- 2
Faça upload de cada arquivo para o endereço tus_url do Assembly Status com um cliente tus, em vez de um POST simples.
- 3
Persista a URL de upload no cliente para que, após recarregamentos ou travamentos, o upload possa ser retomado em vez de recomeçar.
- 4
Assine a requisição de criação da Assembly no seu back-end sempre que o navegador for o cliente.
Quando a Transloadit é útil
Use o Uppy com o plugin da Transloadit no navegador, ou qualquer cliente tus em outros ambientes, e deixe que /upload/handle receba os arquivos. Primeiro crie a Assembly com num_expected_upload_files e depois envie cada arquivo para o endereço tus_url retornado no Assembly Status.
Limite da arquitetura
A retomada de uploads recupera uma transferência interrompida, não uma transferência esquecida. Por padrão, os uploads precisam terminar em até oito horas após a criação da Assembly, e o processamento, em até oito horas após a conclusão do upload. Um limite de processamento específico do Workspace pode alterar a segunda janela. Após a expiração, a Assembly retorna ASSEMBLY_EXPIRED e os bytes já recebidos deixam de ser utilizáveis.
Perguntas frequentes
Preciso implementar o protocolo tus por conta própria?
Geralmente não. O Uppy e os SDKs de back-end usam tus por padrão, então uma integração comum já tem uploads retomáveis. Implementar o protocolo diretamente só faz sentido para criar um SDK ou para usar uma linguagem em que não exista um SDK da Transloadit.
Por que alguns dos meus arquivos nunca apareceram nos resultados?
Verifique se num_expected_upload_files correspondia à quantidade de arquivos pretendida. Depois que essa quantidade tiver chegado, a Assembly deixa de esperar por uploads adicionais. Compare a lista uploads dela com os registros de arquivos do lado do cliente, inspecione as requisições de upload que falharam e conte os arquivos antes de criar a próxima Assembly.
O que acontece se o usuário fechar a aba durante um upload?
A transferência pode ser retomada desde que o cliente tenha guardado a URL de upload e a Assembly não tenha expirado. Persista essa URL fora da memória da página e, ao retornar, envie uma requisição HEAD para descobrir o offset e continuar a partir dele.
Qual é o tamanho máximo de um arquivo para upload?
Arquivos de até 200 GB são suportados, e limites maiores podem ser combinados. A restrição prática costuma ser o tempo, não o tamanho: por padrão, o upload tem oito horas a partir da criação da Assembly, e uma conexão lenta pode esgotar esse prazo antes que um arquivo muito grande termine.
As informações por arquivo devem ir em campos ou em metadados?
Use os metadados de upload do tus quando o valor pertencer a um único arquivo, já que ele chega como uma Assembly Variable em file.user_meta. Use fields apenas para valores compartilhados por todos os arquivos da Assembly, como um identificador de cliente que se aplica ao lote inteiro.