Advanced Usage of tus.io with Node.js
Tags: node, tusio, express
Published: 2023-06-09 15:27:06

In this blog post, we'll delve into an advanced usage of tus.io, a robust open-source protocol for resumable file uploads to servers, with Node.js. The tus.io protocol, combined with the versatility of Node.js, can make file handling operations significantly smoother. We will consider a scenario where we need to upload large files and handle any connection interruptions seamlessly.

## Setup

Firstly, we need to install the necessary libraries. 

```bash
npm install tus-node-server express
```

Here we've installed `tus-node-server`, the Node.js implementation of tus.io, and `express`, a minimal and flexible Node.js web application framework.

## Server Configuration

Let's start by setting up our server:

```javascript
const tus = require('tus-node-server');
const express = require('express');
const server = new tus.Server();

server.datastore = new tus.FileStore({
    path: '/uploads'
});

const app = express();

app.all('*', (req, res) => {
  server.handle(req, res);
});

const host = 'localhost';
const port = 8000;
app.listen(port, host, () => {
  console.log(`Server running on http://${host}:${port}`);
});
```

Here, we're using the built-in `FileStore` datastore, which stores the uploaded files on disk at the specified path. Every request is then passed to our `tus` server to handle.

## Client Configuration

On the client side, we can use the `tus-js-client` to handle the upload. We need to install it first:

```bash
npm install tus-js-client
```

Here is a simple upload example:

```javascript
const tus = require('tus-js-client');
const fs = require('fs');
const path = require('path');

const file = fs.createReadStream(path.resolve(__dirname, 'largefile.txt'));
const size = fs.statSync(path.resolve(__dirname, 'largefile.txt')).size;

const upload = new tus.Upload(file, {
    endpoint: 'http://localhost:8000/files/',
    retryDelays: [0, 1000, 3000, 5000],
    metadata: {
        filename: 'largefile.txt',
        filetype: 'text/plain'
    },
    onError: function(error) {
        console.log("Failed because: " + error)
    },
    onProgress: function(bytesUploaded, bytesTotal) {
        let percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
        console.log(bytesUploaded, bytesTotal, percentage + "%")
    },
    onSuccess: function() {
        console.log("Download %s from %s", upload.file.name, upload.url)
    }
})

upload.start();
```

This script reads the file, prepares it for upload, and sets various callbacks for error handling, progress tracking, and upload success. The `retryDelays` option sets up automatic retries when the upload fails due to a connection interruption.

## Extending Functionality

The beauty of the `tus-node-server` library is in its extensibility. The server emits various events that we can listen for and respond to. For example:

```javascript
server.on(tus.EVENTS.EVENT_UPLOAD_COMPLETE, (event) => {
    console.log(`Upload complete for file ${event.file.id}`);
});
```

## Wrapping up

By leveraging tus.io with Node.js, we can create powerful applications capable of handling large file uploads and connection interruptions seamlessly. While the basic implementation is straightforward, the true power of these tools lies in their flexibility and extensibility.