Uppy uploader rompiéndose con múltiples archivos arrastrados sobre el compositor

Hola,
desde la última actualización (estamos en un entorno administrado) nuestra funcionalidad de carga parece rota, pero no estamos haciendo nada especial.

Simplemente registramos un nuevo api.addComposerUploadHandler() dentro de un componente temático.
Esto solía funcionar muy bien con varios archivos arrastrados al compositor. Ahora, hay errores en la consola que parecen estar relacionados con Uppy (por qué no lo queremos).

Nuestro código es muy simple, pero aun así, Uppy parece interferir con él.

// Registra un manejador de carga personalizado para videos.

    api.addComposerUploadHandler(["mp4", "mov", "mkv", "avi", "m4v"], (file, editor) => {
        console.log("Manejando carga para", file.name);
    })

Arrastrar 3 archivos (mkv, mov, mkv) al compositor muestra el mensaje de error “tu archivo es más grande que 4 MB”, que queríamos evitar en primer lugar, ya que subimos todo a Gdrive.

La consola de Chrome muestra esto:

Arrastrar un solo archivo de 50 MB no causa ese error de “archivo demasiado grande” y nuestro archivo se procesa correctamente, como se esperaba. Por lo tanto, el error parece ocurrir con varios archivos y un archivo más grande que un límite de archivo de 4 MB (no estoy seguro de dónde está establecido esto).

Gracias por cualquier ayuda. Creo que está relacionado con la última actualización de Discourse.

@martin

Hola @Sören_Geier. Ha habido algunos cambios en esta área recientemente, aunque intenté mantener la paridad con el controlador de carga existente en el compositor. Solo quiero tener una mejor idea de tu caso de uso. Por lo que puedo ver, incluso la versión del compositor que no es uppy carga a través de api.addComposerUploadHandler solo maneja un archivo a la vez:

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

Por lo tanto, si sueltas varios archivos, ocurrirá el flujo normal y supongo que en el caso de la OP de este tema simplemente estás alcanzando los límites de tamaño de archivo del flujo de carga normal.

¿Qué solía suceder, o qué esperas que suceda, cuando arrastras y sueltas varios archivos a la vez? Sería útil ver el código de tu componente temático, si no te sientes cómodo compartiéndolo públicamente, puedes enviármelo por mensaje privado aquí en Meta.

Entonces, solo para confirmar, ¿estás alojado por nosotros?

2 Me gusta

Gracias por la rápida respuesta @martin .

Sí, estamos alojando con vosotros. Entonces, lo que suele ocurrir cuando arrastras un archivo al compositor es que inserta algo de texto en el compositor, como “Procesando <nombre_archivo>”… Además, en el caso de usar API.addComposerUploadHandler([“mp4”, “mov”, “mkv”, “avi”, “m4v”]), esto lo hace Discourse antes de entregar el archivo al manejador personalizado aquí. Esa inserción de texto de marcador de posición dejó de funcionar en algún momento, que fue cuando inserté el código yo mismo en mi manejador:

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

Lo siguiente que se rompió fue que nuestro manejador no se activó porque, de repente, esas extensiones de video desaparecieron de la configuración de “extensiones autorizadas del tema”, o tuve que volver a añadirlas allí para que las cosas volvieran a funcionar.

Luego descubrí el problema de arrastrar archivos “múltiples”, como se describió anteriormente.

Lo teníamos funcionando de tal manera que podía arrastrar 2 o más archivos sin que aparecieran mensajes de error. Y también se sentía correcto porque estábamos omitiendo toda esa lógica de validación de Discourse.

Aquí hay fragmentos de código relevantes:

Aquí simplemente espero que Discourse me entregue los archivos arrastrados. Uno tras otro.

// Registra el manejador de carga personalizado para videos.

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

Como Discourse nos entregó los archivos individualmente, creé una función intermediaria que simplemente llena un array y, después de un tiempo de espera, activa la función de carga real. Así que estoy recopilando el archivo pasado de Discourse en mi propio array.

// Recopila todos los archivos arrastrados en secuencia, según lo informado por el manejador de Discourse.
function sendToGDrive(file, api) {
clearTimeout(uploaderStartTimeout);
filesHolder.push(file)
const composerController = api.container.lookup("controller:composer");
composerController.model.appEvents.trigger("composer:insert-block", `[Procesando: ${file.name}...]()`);

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

Luego, cargo cada archivo individualmente en Gdrive.

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

Problemas observados:

  • Las cargas de “múltiples archivos” causan validación del tamaño del archivo, mientras que las cargas de un solo archivo no.
1 me gusta

Gracias por este informe detallado y el código asociado. Ya estaba pensando en algo parecido para los manejadores de carga; permitir que cada archivo que coincida con el manejador entre en una especie de cola o grupo como lo has hecho aquí y luego cargarlos todos a la vez o pasarlos a alguna otra interfaz de usuario, porque encontré extraño el límite de 1 a la vez. Aunque por lo que dices, quizás entendí mal cómo funcionaba el límite de 1 a la vez en el manejador de carga del composer antiguo.

Lo que voy a hacer es algunas pruebas locales para ver qué hacía el cargador antiguo (sin uppy) con varios archivos a través de un manejador de carga con una versión simplificada de la función que proporcionaste en un componente temático, luego intentaré lograr la paridad entre la forma nueva y la forma antigua, porque de todos modos será mucho más flexible que permitir solo un archivo a la vez.

Esto puede llevar un poco de tiempo arreglarlo, trabajaré en ello hoy.

2 Me gusta

Solo quería dar una actualización rápida; confirmé que con los manejadores de carga de composer pre-uppy, aunque el código verifica si solo se carga un archivo, esto no es exacto porque el cargador de archivos de jQuery solo envía un archivo a través de esta ruta de código a la vez, incluso si suelta varios archivos a la vez. Esto contrasta con uppy, que procesa los archivos añadidos en grupos. Esta suposición de un solo archivo a la vez se hace en otros dos complementos que hemos creado y que utilizan api.addComposerUploadHandler, por lo que parece ser un problema común.

Como dije, creo que la mejor manera de avanzar será permitir que este manejador procese varios archivos que luego puedan agruparse y enviarse a otro lugar de una manera que tenga sentido para el autor del complemento/tema. Como mínimo, puedo corregir la suposición del manejador de carga de uppy de que solo se puede enviar un archivo a la vez. Publicaré de nuevo aquí una vez que tenga otra actualización.

2 Me gusta

Una actualización final antes del fin de semana. Tengo esta corrección que debería fusionarse a principios de la próxima semana y que restaurará la “vieja” forma de hacer las cosas de antes de uppy, pero dentro de uppy. Así que tu implementación volverá a funcionar correctamente después de esto:

Sin embargo, también añadiré una PR posterior que cambiará addComposerUploadHandler para que envíe múltiples archivos al callback del manejador en un array, lo que eliminará la necesidad de configurar una cola y callbacks setTimeout para manejar múltiples archivos. Creo que esto es más correcto de todos modos y una mejora general de la API.

Así que tu manejador se convertirá en algo como esto:

// Registra el manejador de subida personalizado para vídeos.
api.addComposerUploadHandler(
  ["mp4", "mov", "mkv", "avi", "m4v"],
  (files, editor) => {
    console.log("Manejando subida para", files.map((file) => file.name).join(", "));
    sendToGDrive(files, api);
  }
);
2 Me gusta

Excelente. ¡Gracias por investigarlo tan rápido!
Que tengas un fin de semana estupendo y merecido :blush:

2 Me gusta

@Sören_Geier Acabo de fusionar DEV: Send multiple files in batches to composer upload handlers when using uppy by martin-brennan · Pull Request #15124 · discourse/discourse · GitHub que cambia uppy para enviar varios archivos a la vez al manejador de subida; necesitarás actualizar tu componente de tema ahora para manejar esto :slight_smile:

3 Me gusta

Genial. Todavía no está implementado, ¿verdad?

¿Estás en nuestro alojamiento Standard? Si es así, ya debería estar desplegado :slight_smile:

3 Me gusta

Okay, he recibido quejas de que las cosas se rompieron para las personas que querían subir archivos.
Ahora lo he investigado y también tuve problemas iniciales para enviar mi archivo a GDRIVE, ya que solo pasé el objeto de archivo. Resultó que el objeto de archivo era una representación envuelta por Uppy del archivo binario, que se veía así.

Para acceder realmente al objeto de archivo nativo, tuve que trabajar con files[0].data. (¿quizás un cambio que rompe la compatibilidad?)

Antes de ese cambio, el manejador simplemente pasaba el objeto de archivo nativo. No estoy seguro de si otras personas experimentarán una funcionalidad rota con este cambio.

Ya tengo todo funcionando. ¡Muchas gracias por la rápida respuesta y el soporte!

3 Me gusta

Oh, vaya, tienes razón, ¡no estoy seguro de cómo me perdí eso cuando hice esa refactorización reciente! :sweat_smile: Enviaré una solución esta mañana, no tardará mucho.

Editar: La solución está aquí, debería implementarse en nuestro hosting estándar en las próximas horas.

3 Me gusta

Genial, ajustamos nuestro código también. Creo que el tema se puede cerrar ahora. Gracias por la ayuda excepcional @martin

1 me gusta

¡No hay problema! Yo hice el desorden, así que es justo que yo lo limpie :sweat_smile:

1 me gusta