Skip to main content

initLocalStorageServer(options)

The initLocalStorageServer function is the core middleware for handling direct file uploads from a user's device to your blocklet's local storage. It leverages the robust Tus resumable upload protocol, ensuring that uploads are reliable and can be resumed after network interruptions.

This middleware is responsible for receiving file chunks, assembling them into a complete file on the server, and triggering callbacks for you to process the file metadata after the upload is complete.

How It Works

The following diagram illustrates the typical data flow when a user uploads a file using the Uploader component connected to a backend with initLocalStorageServer.

Basic Usage

To get started, initialize the middleware in your Express application and mount it on a specific route. The most critical option is onUploadFinish, which is where you'll define what happens after a file is successfully saved.

Basic Backend Setup

javascript
import express from 'express';
import { initLocalStorageServer } from '@blocklet/uploader-server';
import Upload from '../models/upload'; // Your database model

const router = express.Router();

// Initialize the uploader server middleware
const localStorageServer = initLocalStorageServer({
  // The directory where uploaded files will be stored
  path: process.env.UPLOAD_DIR,
  express,

  // This callback executes after a file is successfully uploaded
  onUploadFinish: async (req, res, uploadMetadata) => {
    const {
      id: filename, // The unique, randomized filename on disk
      size,
      metadata: { filename: originalname, filetype: mimetype },
    } = uploadMetadata;

    // Construct the public URL for the uploaded file
    const fileUrl = new URL(process.env.APP_URL);
    fileUrl.pathname = `/uploads/${filename}`;

    // Save file information to your database
    const doc = await Upload.insert({
      mimetype,
      originalname,
      filename,
      size,
      url: fileUrl.href,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
      createdBy: req.user.did,
    });

    // Return the database document as a JSON response
    // This data will be passed to the frontend's onUploadFinish callback
    return doc;
  },
});

// Mount the middleware on the '/uploads' route
// Ensure any necessary authentication/authorization middleware runs before it
router.use('/uploads', yourAuthMiddleware, localStorageServer.handle);

export default router;

Configuration Options

The initLocalStorageServer function accepts an options object with the following properties:

OptionTypeRequiredDescription
pathstringYesThe absolute path to the directory where uploaded files will be stored.
expressFunctionYesThe Express application instance.
onUploadFinishFunctionNoAn async callback function that runs after a file upload is complete. It receives (req, res, uploadMetadata). The return value is sent as a JSON response to the frontend.
onUploadCreateFunctionNoAn async callback function that runs when a new upload is initiated but before any data is transferred. Useful for validation or authorization checks. It receives (req, res, uploadMetadata).
expiredUploadTimeNumberNoThe time in milliseconds after which incomplete uploads are considered expired and will be cleaned up by a background job. Default: 1000 * 60 * 60 * 24 * 3 (3 days).
...restPropsobjectNoAny other valid options for the underlying @tus/server package will be passed through.

Callbacks in Detail

onUploadFinish(req, res, uploadMetadata)

This is the primary callback for processing completed uploads. It's the ideal place to save file metadata to your database, trigger webhooks, or perform other post-upload actions.

uploadMetadata Object

The uploadMetadata object passed to the callback contains detailed information about the uploaded file:

PropertyTypeDescription
idstringThe unique, randomly generated filename on the server's disk.
sizenumberThe total size of the file in bytes.
offsetnumberThe current number of bytes uploaded. Should equal size in this callback.
metadataobjectAn object containing metadata provided by the client.
metadata.filenamestringThe original filename from the user's computer.
metadata.filetypestringThe MIME type of the file (e.g., image/jpeg).
runtimeobjectAn object with runtime information about the file's location.
runtime.absolutePathstringThe full path to the file on the server's filesystem.

Return Value

The value you return from onUploadFinish will be serialized into JSON and sent back to the frontend Uploader component. This allows you to pass back the database record ID, the public URL, or any other relevant data.

Automatic Cleanup

The middleware automatically sets up a background cron job (auto-cleanup-expired-uploads) that runs hourly. This job safely removes any partial or expired uploads from the storage directory that have exceeded the expiredUploadTime, preventing your server from filling up with incomplete files.

Advanced Features

EXIF Data Removal

For privacy and security, the middleware automatically attempts to strip EXIF (Exchangeable image file format) metadata from uploaded images (.jpeg, .tiff, etc.) after the upload is complete.

Manual File Deletion

The returned server instance includes a delete method you can use to programmatically remove an uploaded file and its associated metadata file.

Manually Deleting a File

javascript
import { localStorageServer } from './setup'; // Assuming you exported the instance

async function deleteFile(filename) {
  try {
    await localStorageServer.delete(filename);
    console.log(`Successfully deleted ${filename}`);
  } catch (error) {
    console.error(`Failed to delete ${filename}:`, error);
  }
}

Now that you know how to handle direct uploads, you might want to enable users to import files from external services. Proceed to the next section to learn about initCompanion.

Next: initCompanion(options)

Learn how to set up the Companion middleware to allow users to import files from remote sources like Unsplash and direct URLs.