Экспресс ГрафикаМагия

В настоящее время я создаю приложение MEAN, и раздел, над которым я сейчас работаю, включает загрузку изображений. Я пытаюсь использовать GraphicsMagick для Node, но у меня ничего не получается. Ниже приведен мой запрос POST для загрузки изображений (как есть):

app.post('/api/users/upload_image', function (req, res) {
        var fstream;
        req.pipe(req.busboy);
        req.busboy.on('file', function (fieldname, file, filename) {
            console.log('\n\nUploading file: '.underline.bold +filename .underline.bold);


            // var readStream = fs.createReadStream(filename);
            // gm(readStream, readStream.path)
            //  .resize('200','200')
            //  .stream(function (err, stdout, stderr) {
            //      var writeStream = fs.createWriteStream('www/uploads/' + readStream.path);
            //      stdout.pipe(writeStream);
            //  });

            fstream = fs.createWriteStream('www/uploads/' + filename);
            file.pipe(fstream);

        });

        req.busboy.on('finish', function () {
            res.writeHead(303, { Connection: 'close', Location: '/' });
            res.end();
        });
    });

Закомментированный раздел - это моя попытка использовать GM, но это возвращает ошибку: Error: ENOENT, open '[filename].jpg'

Где я ошибаюсь? Это моя первая попытка использовать GM, поэтому я новичок в этой библиотеке!


person leaksterrr    schedule 25.05.2014    source источник
comment
Файл вообще есть? Что произойдет, если вы используете GraphicsMagick вне HTTP-запроса, чтобы определить, связана ли проблема с вашим вызовом gm или с подключением запроса к gm?   -  person Buck Doyle    schedule 26.05.2014
comment
Да, файл существует, потому что код в приведенном выше блоке сохраняет изображение, которое передается через форму, на сервер. Проблема, похоже, в том, что GM перехватывает файл до его сохранения.   -  person leaksterrr    schedule 26.05.2014


Ответы (2)


var readStream = fs.createReadStream(filename);

в этой строке файла с именем имя_файла на самом деле нет, но вы пишете этот файл под закомментированными строками. То, что у вас есть, это прочитанный пар под названием file, который вы получаете от busyboy. поэтому избавьтесь от этой строки и передайте file непосредственно gm

gm(file,....

Код ниже делает именно то, что вы хотите, обратите внимание на параметры функции записи gm.

app.post('/api/users/upload_image', function (req, res) {
    req.pipe(req.busboy);
    req.busboy.on('file', function (fieldname, file, filename) {
        console.log('\n\nUploading file: '.underline.bold +filename .underline.bold);

        console.log('Resizing file...');

        gm(file,'www/uploads/' + filename)
        .resize(200,200)
        .write('www/uploads/' + filename, function (err) {
            console.log("finished");
        });
    });

    req.busboy.on('finish', function () {
        res.writeHead(303, { Connection: 'close', Location: '/' });
        res.end();
    });
});

Обратите внимание, что изменение размера gm при таком использовании просто вмещает изображение в поле 200x200, а не точно масштабирует / растягивает его до 200x200.

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

person Quad    schedule 25.05.2014
comment
Если я сделаю это, а затем передам имя файла в поток записи вместо readstream.path, я получу ошибку: написать EPIPE? - person leaksterrr; 26.05.2014
comment
В какой именно строке вы получаете EPIPE? EPIPE означает, что другой конец закрыл поток до завершения чтения/записи. - person Quad; 26.05.2014
comment
На самом деле это не дает линейной ошибки, характерной для этой функции, вы можете увидеть полную ошибку, которую я получаю в ответе выше вашего. Я получаю ту же ошибку с обоими решениями. - person leaksterrr; 26.05.2014
comment
в этом случае попытайтесь найти, какой стим выдает эту ошибку. Сначала вытащите .steam( и используйте write от gm. Если вы все еще получаете сообщение об ошибке, это означает, что ошибка исходит от file readsteam официанта. - person Quad; 26.05.2014
comment
У меня это работает, но я не уверен, что это правильно... Вот что у меня есть: pastie.org/pastes/9214877/text?key=7zwffbkme4ov4p3nqhg - это сохранение файла из gm, что, я думаю, является шагом в правильном направлении, но проблема, с которой я сейчас в том, что .resize gm не работает, и файл сохраняется на сервере с исходным размером вместо 200x200. Я пробовал 200,200 и "200", "200" - person leaksterrr; 26.05.2014
comment
write принимает имя файла в качестве первого параметра .write('/path/to/file.png', function (err) { if (!err) console.log('done'); }); - person Quad; 26.05.2014
comment
Да, это то, что я пробовал из другого ответа, и этот блок возвращает EPIPE. Я не вижу, как соединение закрывается? - person leaksterrr; 26.05.2014
comment
Можете ли вы загрузить небольшой проект, изолированный от этой проблемы? - person Quad; 26.05.2014
comment
на самом деле это не сработало бы, потому что это происходит в CLI. Вот полный запрос POST upload_image: qswnycucptrtb3pbsmvojq - person leaksterrr; 26.05.2014
comment
Я имел в виду проект nodejs, заархивированный и загруженный куда-то, чтобы я мог запустить проект в своей локальной тестовой среде node и посмотреть, что это такое. - person Quad; 26.05.2014
comment
Давайте продолжим обсуждение в чате. - person Quad; 26.05.2014

Проблема в том, что вы пытаетесь прочитать файл до того, как он будет записан. Если вам не нужно сохранять исходное изображение, вы можете просто передать файл непосредственно в gm:

req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
    console.log('\n\nUploading file: '.underline.bold +filename .underline.bold);

    console.log('Resizing file...');
    gm(file, filename)
     .resize('200','200')
     .write('www/uploads/' + filename, function(err) {
       if (err) throw err; // handle better
       console.log('Success!'.bold);
     });
});

Вероятно, вам также следует проверить, соответствует ли данный тип mime файла тому, что вы ожидаете (например, image/jpeg, image/png и т. д.). Вы также можете пойти дальше, используя что-то вроде mmmagic для проверки типа файла. Однако с mmmagic вам придется отказаться от прямой потоковой передачи в gm и сначала сохранить файл на диск.

person mscdex    schedule 25.05.2014
comment
Я сделал именно так, как вы сказали здесь, и теперь я получаю совершенно другое сообщение, которое я не понимаю (пытался его отформатировать): events.js:72 ... throw er; // Unhandled 'error' event ... Error: write EPIPE at ... errnoException (net.js:904:11) ... at Object.afterWrite (net.js:720:19) - person leaksterrr; 26.05.2014