How to upload file in Hapi


file hapi nodejs Tutorials

In this tutorial, we will learn how to handle file uploading in Hapi. We will discover the next cases: binary data and stream.

Introduction

In this tutorial, we will use the following Hapi server:

'use strict';

const Hapi = require('hapi');

const server = Hapi.server({
    port: 3000,
    host: 'localhost'
});

server.route({
    method: 'POST',
    path: '/submit',
    options: {
        handler: async (req, h) => {
            return h.response({
                file: 'test.png'
            });
        }
    }

});

const init = async () => {
    await server.start();
    console.log(`Server running at: ${server.info.uri}`);
};

process.on('unhandledRejection', (err) => {
    console.log(err);
    process.exit(1);
});

init();

We will change the logic of POST /submit route to support file uploading.

Uploading binary file data

Let’s set the correct payload format to allow us binary upload:

server.route({
    method: 'POST',
    path: '/submit',
    options: {
        payload: {
            parse: true,
            output: 'file',
        },
        handler: async (req, h) => {
            console.log(req.payload);
            return h.response(req.payload);
        }
    }
});

If we send the binary data, we will get the next data on server:

{
    "path": "/var/folders/np/jsrf9yb15w745z7zf6_dr_c80000gn/T/1546782771308-8044-68b83a64d7d23bf4",
    "bytes": 20374
}
  • **path **- the temporary path to uploaded file
  • **bytes **- the size of file

Then we can make any actions with the file using the path to this file.

Uploading data or file as stream

If we send the data as stream, we need to change payload to the following:

payload: {
  output: 'stream',
  parse: true
}

Suppose, we have the following HTML form and sends these data to our POST /submit endpoint:

<form action="/submit" method="post" enctype="multipart/form-data">
    <input type="file" name="image"/>
    <input type="text" name="imageName"/>
    <button type="submit">Submit</button>
</form>

Now, in route handler we can get our image and imageName data in payload object:

server.route({
    method: 'POST',
    path: '/submit',
    options: {
        payload: {
            output: 'stream',
            parse: true
        },
        handler: async (req, h) => {
            console.log(req.payload.image);
            console.log(req.payload.imageName);
            return h.response('req.payload');
        }
    }
});

The req.payload.image will contains the Readable Stream object. We can get more information about file name and headers using hapi object in req.payload.image. We should see something similar to the next object:

{ filename: 'Pinlight Studio (6).png',
    headers:
    { 'content-disposition': 'form-data; name="image"; filename="Pinlight Studio (6).png"',
    'content-type': 'image/png' }
}

If you want to save a readable stream to file, I recommend you to follow this tutorial.

Learning Hapi.js? Buy my Hapi.js Handbook🔥

comments powered by Disqus