Загрузка файла HapiJs: 500 Внутренняя ошибка сервера при загрузке больших файлов, ответ никогда не доходит до вызывающего - PullRequest
0 голосов
/ 07 марта 2019

Мы используем IISNODE для размещения нашего приложения узла, написанного с использованием "hapi": "^ 16.5.2", маршрут вставлен ниже

{ 
    method: 'POST',
    path: '/xxxx/xxxx/xxxx/Upload/',
    config: {
        auth: { strategies: ['simple'] },
        handler: uploadHandler.Upload,
        plugins: {
            'hapi-swagger': {
                responses: fileHTTPStatus,
                payloadType: 'form'
            },
            disinfect: {
                disinfectQuery: false,
                disinfectParams: false,
                disinfectPayload: false
            },
            policies: ['MethodAudit']
        },
        tags: ['api'],
        validate: {
            payload: {
                file: Joi.any().meta({ swaggerType: 'file' }).required().description('file')
            }
        },
        payload: {
            maxBytes: 209715200,
            parse: true,
            allow: 'multipart/form-data',
            output: 'stream'
        },
        cors: {
            origin: ['*'],
            additionalHeaders: ['cache-control', 'x-requested-with', 'accept', 'authorization', 'content-type', 'if-none-match', 'origin', 'Accept-language']
        }
    }
}

метод uploadHandler.Upload выглядит следующим образом:

function Upload (request, reply) {
if (request.payload) {
    var data = request.payload;

    if (data.file) {

        var originalName = data.file.hapi.filename;

        var path = rootDocPath + originalName; //rootDocPath is our common location

        var file = fs.createWriteStream(path);

        file.on('error', function (err) {
            console.error(err)
        });

        data.file.pipe(file);

        file.on('end', function() {
            console.log('file ended');
        });

        file.on('finish', function() {
            console.log('file finished');
        });

        data.file.on('end', function(err) {
            console.log('data.file ended');
        });

        file.on('close', function(err) {
            reply('Uploaded');
        });

    } else {
        reply('no file')
    }
} else {
    reply('no payload')
}

}

Ответ, который мы получаем: Подробная ошибка IIS 8.5 - 500.1013 - Внутренняя ошибка сервера

  • Во время отладки мы могли видеть, что ответ («Загружен») выполняется, но ответ никогда не принимается вызывающей стороной.
  • Такое поведение проявляется только при использовании более крупных файлов (более 1,9 МБ), для небольших файлов работает 100%

Ответы [ 2 ]

0 голосов
/ 11 марта 2019

Исправление, которое работало для меня, состояло в том, чтобы установить полезную нагрузку запроса в нуль перед отправкой ответа вызывающей стороне.Похоже, если размер полезной нагрузки запроса слишком велик, служба не может ответить.Пожалуйста, смотрите исправление ниже (ищите комментарий Это ИСПРАВЛЕНИЕ ):

function Upload (request, reply) {
 if (request.payload) {
    var data = request.payload;

    if (data.file) {

        var originalName = data.file.hapi.filename;

        var path = rootDocPath + originalName; //rootDocPath is our common location

        var file = fs.createWriteStream(path);

        file.on('error', function (err) {
            console.error(err)
        });

        data.file.pipe(file);

        file.on('end', function() {
            console.log('file ended');
        });

        file.on('finish', function() {
            console.log('file finished');
        });

        data.file.on('end', function(err) {
            console.log('data.file ended');
        });

        file.on('close', function(err) {
            request.payload.file = null; /*This is the FIX*/
            reply('Uploaded');
        });

    } else {
        reply('no file')
    }
 } else {
     reply('no payload')
 }
}
0 голосов
/ 07 марта 2019

Возможно, что-то происходит в вашей потоковой трубе.

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

const fileUploader = function (file, targetPath) {
    if (!file) throw new Error('no file');
    const fileStream = fs.createWriteStream(targetPath);

    return new Promise((resolve, reject) => {
        file.on('error', function (err) {
            reject(err);
        });

        file.pipe(fileStream);

        file.on('end', function (err) {
            resolve({
                fieldname: file.hapi.name,
                originalname: file.hapi.filename,
                mimetype: file.hapi.headers['content-type'],
                targetPath,
                size: fs.statSync(targetPath).size,
            });
        })
    })
};

// usage
const filePath = await helpers.fileUploader(request.payload.data, targetPath);
...