Uppy uploader quebrando com múltiplos arquivos arrastados para o composer

Olá,
desde a última atualização (estamos em um ambiente gerenciado), nossa funcionalidade de upload parece ter quebrado, mas não estamos fazendo nada de especial.

Nós simplesmente registramos um novo api.addComposerUploadHandler() de dentro de um componente de tema.
Isso costumava funcionar muito bem com vários arquivos arrastados para o composer. Agora, há erros lançados no console que parecem estar relacionados ao Uppy (o que não queremos).

Nosso código é muito simples, mas ainda assim, o Uppy parece interferir nele.

// Registra um manipulador de upload personalizado para vídeos.

	api.addComposerUploadHandler(["mp4", "mov", "mkv", "avi", "m4v"], (file, editor) => {
		console.log("Lidando com o upload de", file.name);
	})

Soltar 3 arquivos (mkv, mov, mkv) no composer mostra a mensagem de erro “seu arquivo é maior que 4 MB”, que queríamos ignorar em primeiro lugar, pois enviamos tudo para o Gdrive.

O console do Chrome lança estes:

Soltar um único arquivo de 50 MB não causa esse “erro de arquivo muito grande” e nosso arquivo é processado corretamente, como esperado. Portanto, o erro parece estar acontecendo com vários arquivos e um arquivo maior que um limite de arquivo de 4 MB (não tenho certeza de onde isso é definido).

Obrigado por qualquer ajuda. Acho que está relacionado à última atualização do próprio Discourse.

@martin

Olá @Sören_Geier. Houve algumas alterações nesta área recentemente, embora eu tenha tentado manter a paridade com o manipulador de upload existente no composer. Só quero ter uma ideia melhor do seu caso de uso. Pelo que pude verificar, mesmo a versão não-uppy do composer faz upload via api.addComposerUploadHandler lida apenas com um arquivo por vez:

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/mixins/composer-upload.js#L215-L222

Portanto, se você soltar vários arquivos, o fluxo normal acontecerá, e eu acho que no caso do OP deste tópico você está simplesmente atingindo os limites de tamanho de arquivo do fluxo de upload normal.

O que costumava acontecer, ou o que você espera que aconteça, quando você arrasta e solta vários arquivos de uma vez? Seria útil ver o código do seu componente de tema, se você não se sentir confortável em compartilhá-lo publicamente, pode me enviar uma mensagem privada aqui no Meta.

Então, apenas para confirmar, você é hospedado por nós?

2 curtidas

Obrigado pela resposta rápida, @martin.

Sim, estamos hospedando com você. Então, o que normalmente acontece quando você arrasta um arquivo para o composer é que ele insere algum texto no composer, como “Processando ”… Além disso, no caso de usar API.addComposerUploadHandler([“mp4”, “mov”, “mkv”, “avi”, “m4v”]), isso é feito pelo Discourse antes de entregar o arquivo ao manipulador personalizado aqui. Essa inserção de texto de placeholder parou de funcionar em algum momento, que foi quando eu inseri o código em meu manipulador:

composerController.model.appEvents.trigger("composer:insert-block", `[Processando: ${file.name}...]()`);

A próxima coisa que quebrou foi que nosso manipulador não foi ativado porque, de repente, essas extensões de vídeo desapareceram da configuração “extensões autorizadas do tema” - ou eu tive que adicioná-las novamente lá para que as coisas começassem a funcionar novamente.

Então, descobri o problema de arrastar “múltiplos” arquivos, como descrito anteriormente.

Nós tínhamos funcionando de uma forma que eu conseguia arrastar 2+ arquivos sem mensagens de erro. E também parecia correto porque estávamos contornando toda a lógica de validação do Discourse.

Aqui estão trechos de código relevantes:

Aqui eu simplesmente espero que o Discourse me entregue os arquivos arrastados. Um após o outro.

// Registra o manipulador de upload personalizado para vídeos.

api.addComposerUploadHandler(["mp4", "mov", "mkv", "avi", "m4v"], (file, editor) => {
console.log("Lidando com o upload para", file.name);
sendToGDrive(file, api);
})

Como o Discourse nos entregou os arquivos individualmente, criei uma função intermediária que simplesmente preenche um array e, após um tempo limite, inicia a função de upload real. Então, estou coletando o arquivo passado do Discourse em meu próprio array.

// Coleta todos os arquivos arrastados em sequência - conforme relatado pelo manipulador do Discourse.
function sendToGDrive(file, api) {
clearTimeout(uploaderStartTimeout);
filesHolder.push(file)
const composerController = api.container.lookup("controller:composer");
composerController.model.appEvents.trigger("composer:insert-block", `[Processando: ${file.name}...]()`);

uploaderStartTimeout = setTimeout(function () {
initFileSend(api);
}, 300);
}

Então, eu faço o upload de cada arquivo individualmente para o Gdrive.

// Lida com cada arquivo individualmente.
async function initFileSend(api) {
for (const file of filesHolder) {
const content = await sendFileToGdrive(file, api, uploadFolderId);
}
}

Problemas observados:

  • Drops de “múltiplos arquivos” causam validação de tamanho de arquivo, enquanto drops de arquivo único não.
1 curtida

Obrigado por este relatório detalhado e pelo código associado. Eu já estava pensando nessa linha de raciocínio para os manipuladores de upload; permitindo que cada arquivo que corresponda ao manipulador entre em uma espécie de fila ou pool como você fez aqui e, em seguida, faça o upload de todos de uma vez ou os passe para alguma outra interface do usuário, porque eu achei estranho o limite de 1 por vez. Embora, pelo que você está dizendo, talvez eu tenha entendido mal como o limite de 1 por vez funcionava no manipulador de upload do antigo composer.

O que vou fazer é alguns testes locais para ver o que o antigo uploader sem uppy fazia com vários arquivos através de um manipulador de upload com uma versão simplificada da função que você forneceu em um componente de tema, depois tentarei alcançar paridade entre a nova maneira e a antiga, porque será muito mais flexível do que permitir apenas um arquivo por vez.

Isso pode levar um tempo para consertar, vou trabalhar nisso hoje.

2 curtidas

Gostaria de dar uma atualização rápida; confirmei que com os manipuladores de upload do composer pre-uppy, embora o código verifique se apenas um arquivo é enviado, isso não é preciso porque o uploader de arquivos do jQuery envia apenas um arquivo por vez por este caminho de código, mesmo que você solte vários arquivos de uma vez. Isso é em contraste com o uppy, que processa os arquivos adicionados em grupos. Essa suposição de um arquivo por vez é feita em outros dois plugins que criamos que utilizam api.addComposerUploadHandler, então parece ser um problema comum.

Como eu disse, acho que a melhor maneira de seguir em frente será permitir que este manipulador processe vários arquivos que podem então ser agrupados e enviados para outro lugar de uma maneira que faça sentido para o autor do plugin/tema. No mínimo, posso corrigir a suposição do manipulador de upload do uppy de que apenas um arquivo pode ser enviado por vez. Postarei novamente aqui assim que tiver outra atualização.

2 curtidas

Uma atualização final antes do fim de semana. Tenho este conserto que deve ser mesclado no início da próxima semana e que restaurará a “maneira antiga” de fazer as coisas do pré-uppy, mas dentro do uppy. Assim, sua implementação voltará a funcionar corretamente após isto:

No entanto, também adicionarei um PR subsequente que alterará addComposerUploadHandler para enviar múltiplos arquivos para o callback do manipulador em um array, o que removerá a necessidade de você configurar uma fila e callbacks setTimeout para lidar com múltiplos arquivos que chegam. Acho que isso é mais correto de qualquer forma, e uma melhoria geral da API.

Assim, seu manipulador se tornará algo como isto:

// Registra o manipulador de upload personalizado para vídeos.
api.addComposerUploadHandler(
  ["mp4", "mov", "mkv", "avi", "m4v"],
  (files, editor) => {
    console.log("Lidando com o upload para", files.map((file) => file.name).join(", "));
    sendToGDrive(files, api);
  }
);
2 curtidas

Excelente. Obrigado por investigar tão rapidamente!
Tenha um ótimo e merecido fim de semana :blush:

2 curtidas

@Sören_Geier Acabei de mesclar DEV: Send multiple files in batches to composer upload handlers when using uppy by martin-brennan · Pull Request #15124 · discourse/discourse · GitHub que muda o uppy para enviar vários arquivos de uma vez para o manipulador de upload; você precisará atualizar seu componente de tema agora para lidar com isso :slight_smile:

3 curtidas

Ótimo. Ainda não foi implantado, certo?

Você está em nossa hospedagem Standard? Se sim, já deve ter sido implantado :slight_smile:

3 curtidas

Ok, recebi reclamações de que as coisas quebraram para as pessoas que queriam fazer upload.
Eu investiguei e também tive problemas iniciais para enviar meu arquivo para o GDRIVE, pois passei apenas o objeto do arquivo. Descobriu-se que o objeto do arquivo era uma representação encapsulada pelo Uppy do arquivo binário, parecendo assim.

Para realmente acessar o objeto de arquivo nativo, tive que trabalhar com files[0].data. (talvez uma mudança que quebra a compatibilidade?)

Antes dessa mudança, o manipulador apenas passava o objeto de arquivo nativo. Posso esperar que outras pessoas experimentem funcionalidades quebradas com essa mudança, não tenho certeza.

Consegui fazer tudo funcionar agora. Muito obrigado pela rápida resposta e suporte!

3 curtidas

Puxa, você tem razão, não sei como deixei isso passar durante a refatoração recente! :sweat: Vou enviar uma correção para isso esta manhã, não vai demorar muito.

Editar: A correção está aqui, deve ser implantada em nossa hospedagem padrão nas próximas horas.

3 curtidas

Ótimo, ajustamos nosso código também. Acho que o tópico pode ser encerrado agora. Obrigado pela ajuda excepcional, @martin

1 curtida

Sem problema! Eu fiz a bagunça, então é justo que eu a limpe :sweat_smile:

1 curtida