Uploads diretos de arquivo
Os uploads diretos de arquivo permitem que você transmita os fluxos multipartes recebidos para um serviço de nuvem como Amazon S3 ou Cloudinary sem processá-los em seu servidor. O fluxo é o seguinte:
- O usuário carrega o arquivo.
- A solicitação chega ao seu servidor.
- Em vez de analisar a solicitação e ler dados dela, você canaliza o fluxo para um serviço de nuvem externo.
Como você canaliza o fluxo diretamente, seu aplicativo AdonisJS não precisa alocar nenhuma memória adicional ou computação de CPU para analisar e persistir os dados em um disco.
Quando não usar uploads diretos de arquivo?
Como você notará mais adiante neste guia, os uploads diretos de arquivo são complexos, pois você lida com os fluxos diretamente.
Recomendamos manter os uploads de arquivo padrão se seu aplicativo não lida com uploads de arquivos grandes. Lembre-se, às vezes escrever o código mais simples vence pequenos ganhos de desempenho.
Uso
O primeiro passo é desabilitar o autoprocessamento de arquivos dentro do arquivo config/bodyparser.ts
. Uma vez desabilitado o autoprocessamento, o middleware bodyparser encaminhará o fluxo multipartes para seu controlador para que você possa processá-lo manualmente.
Você pode desabilitar o autoprocessamento para todo o aplicativo definindo a propriedade autoProcess
como false
.
multipart: {
autoProcess: false
}
Ou você pode desabilitá-lo para rotas selecionadas adicionando seu padrão de rota ao array processManually
.
processManually: ['/drive']
Manipulando o fluxo multipartes
Você pode manipular o fluxo multipartes dentro do seu controlador da seguinte forma:
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class DriveController {
public async store({ request }: HttpContextContract) {
request.multipart.onFile('input_field_name', {}, (part) => {
someSdk.uploadStream(part)
})
await request.multipart.process()
}
}
- O
request.multipart.process()
inicia o processamento do fluxo multipartes. - O método
request.multipart.onFile
permite que você processe o fluxo para uma determinada entrada de arquivo definindo um retorno de chamada. - O método de retorno de chamada recebe a instância do fluxo (
part
) como o primeiro argumento. Você pode escrever esse fluxo em qualquer destino que desejar.
Acesse o arquivo de fluxo processado
Depois que o fluxo de um determinado arquivo for processado (com sucesso ou com erros), você pode acessá-lo usando o método request.file
. Por exemplo:
request.multipart.onFile('input_field_name', {}, (part) => {
someSdk.uploadStream(part)
})
await request.multipart.process()
const file = request.input('input_field_name')
if (file.hasErrors) {
return file.errors
}
Validando o fluxo
Você também pode validar o fluxo conforme ele é gravado em um destino, relatando cada pedaço para uma função auxiliar passada como o segundo argumento para o retorno de chamada onFile
.
request.multipart.onFile(
'input_field_name',
{
extnames: ['pdf', 'jpg', 'png', 'doc', 'xls'],
size: '200mb',
},
(part, reportChunk) => {
part.pause()
part.on('data', reportChunk)
someSdk.uploadStream(part)
})
- Primeiro, você precisa definir as regras de validação para
extname
esize
. - Em seguida, use o método
reportChunk
e relate cada pedaço para uma função auxiliar interna. - O método
reportChunk
monitorará o fluxo conforme ele flui e emitirá um erro se alguma regra de validação não for atendida. - Assim que um erro for emitido pelo método
reportChunk
no fluxo legível, o fluxo gravável (seu SDK) irá/deve abortar o processo de upload.
Você notou a declaração part.pause
?
Você tem que pausar o fluxo antes de definir o ouvinte de evento part.on('data')
. Caso contrário, o fluxo começará a fluir dados antes que seu SDK esteja pronto para consumi-los.
Tratamento de erros
Quaisquer erros que ocorreram dentro do retorno de chamada onFile
são adicionados à instância do arquivo, e você pode acessá-los da seguinte forma.
request.multipart.onFile('input_field_name', {}, (part) => {
throw new Error('blow up the stream')
})
await request.multipart.process()
const file = request.input('input_field_name')
console.log(file.errors) // conterá o "explodir o fluxo"
Anexar metadados ao fluxo processado
Você pode anexar metadados ao arquivo de fluxo processado retornando um objeto do retorno de chamada onFile
. Por exemplo, pode ser um objeto que contém a URL do arquivo carregado para um serviço de nuvem.
request.multipart.onFile('input_field_name', {}, (part, reportChunk) => {
part.pause()
part.on('data', reportChunk)
const url = await someSdk.uploadStream(part)
return { url }
})
O url
estará disponível na propriedade file.meta
.
await request.multipart.process()
const file = request.input('input_field_name')
console.log(file.meta) // { url: '...' }
Advertências
Ao trabalhar com o fluxo diretamente, você não pode acessar os campos de entrada do formulário antes de processar o fluxo inteiro. Isso ocorre porque os campos e arquivos do formulário são partes de um único fluxo e, portanto, estão disponíveis apenas quando o fluxo é processado.
ERRO
O campo do formulário pode não estar disponível durante o processamento do fluxo
request.multipart.onFile('input_field_name', {}, (part) => {
// Pode ou não estar disponível, com base na posição do campo
// no fluxo
request.input('some_field')
})
await request.multipart.process()
SUCESSO
Acesse o campo do formulário após o fluxo ter sido processado
request.multipart.onFile('input_field_name', {}, (part) => {
})
await request.multipart.process()
// Acesso após o método do processo
request.input('some_field')
Qual é a diferença dos uploads diretos da AWS?
AWS permite uploads diretos de arquivos diretamente do navegador, sem nem mesmo atingir seu servidor.
Uploads diretos do AdonisJS são uma alternativa aos uploads diretos da AWS, mas ambas as abordagens têm suas vantagens e desvantagens, conforme listado abaixo.
Uploads diretos da AWS
- Processado diretamente do navegador.
- Requer uma solicitação HTTP adicional para gerar uma assinatura de autenticação. Propriedade file.type para detectar o tipo de conteúdo do arquivo. Isso pode ser facilmente falsificado.
- Precisa de uma política de bucket para validar o tipo e o tamanho do arquivo.
- Os uploads de arquivos são geralmente mais rápidos e não exigem computação nenhuma em seu servidor.
Uploads diretos do AdonisJS
- Processado do servidor.
- Usa o arquivo número mágico para detectar o tipo de conteúdo do arquivo no servidor.
- Usa as validações padrão do lado do servidor.
- Mesmo que os arquivos sejam transmitidos diretamente, seu servidor ainda precisa atender à solicitação.