Невозможно использовать один читаемый поток для записи в две разные цели в Node JS - PullRequest
0 голосов
/ 10 июля 2020

У меня есть клиентское приложение, в которое пользователи могут загружать изображения. Я получаю это изображение в своем приложении Node JS как читаемые данные, а затем манипулирую им перед сохранением следующим образом:

uploadPhoto: async (server, request) => {  

        try {         

            const randomString = `${uuidv4()}.jpg`;
            
            const stream = Fse.createWriteStream(`${rootUploadPath}/${userId}/${randomString}`);

            const resizer = Sharp()
                                .resize({
                                    width: 450
                                });

            await data.file
                    .pipe(resizer)
                    .pipe(stream);

Это работает нормально и записывает файл в локальный каталог проекта. Проблема возникает, когда я снова пытаюсь использовать те же читаемые данные в той же функции asyn c. Обратите внимание, весь этот код находится в блоке try.

        const stream2 = Fse.createWriteStream(`${rootUploadPath}/${userId}/thumb_${randomString}`);

        const resizer2 = Sharp()
                            .resize({
                                width: 45
                            });

        await data.file
                .pipe(resizer2)
                .pipe(stream2);

Второй файл записан, но когда я проверяю файл, он кажется поврежденным или не удалось успешно записать данные. Первое изображение всегда в порядке.

Я пробовал несколько вещей и нашел один метод, который, кажется, работает, но я не понимаю почему. Я добавляю этот код непосредственно перед созданием второго потока записи:

    data.file.on('end', () => {
        console.log('There will be no more data.');
    });

Помещение кода для второго потока записи внутри блока обратного вызова на конце не имеет значения, однако, если я оставлю код вне блока, между первым кодом потока записи и вторым кодом потока записи, тогда он работает, и оба файла успешно записаны.

Неправильно оставлять код таким, какой он есть . Есть ли лучший способ написать изображение второго ногтя большого пальца? Я пытался использовать модуль Sharp для чтения файла после того, как первый поток записи записывает данные, а затем создать его уменьшенную версию, но это не работает. Кажется, что файл никогда не готов к использованию.

1 Ответ

1 голос
/ 10 июля 2020

У вас есть 2 альтернативы, которые зависят от того, как разработано ваше программное обеспечение.

Если возможно, я бы избегал выполнять две операции преобразования в одном потоке в одном и том же «контексте», например: конечная точка API . Я бы предпочел разделить эти две разные трансформации, чтобы они не работали с одним и тем же входным потоком.

Если это невозможно или потребует слишком много изменений, решение состоит в том, чтобы разделить входной поток и направить его в два разных Writable. Обычно я использую Highland. js fork для этих задач.

Также смотрите мои комментарии о том, как правильно обрабатывать потоки с помощью async / await, чтобы проверить, когда операция записи завершена.

...