Storage ClientIntroduction

Introduction

Simple and easy file uploads for React, Vue, Solid, and Svelte

Storage Client

Simple and easy file uploads for React | Vue | Solid | Svelte

The Visulima Storage Client is a powerful, framework-agnostic library for handling file uploads in modern web applications. It provides a unified API across React, Vue, Nuxt, Solid, and Svelte with support for multiple upload methods, progress tracking, retry mechanisms, and batch operations.

Features

  • Framework Support - First-class support for React, Vue/Nuxt, Solid, and Svelte
  • Multiple Upload Methods - Multipart (form-based), TUS (resumable), and chunked REST uploads
  • Auto-detection - Automatically selects the best upload method based on file size and available endpoints
  • Progress Tracking - Real-time upload progress with percentage and byte-level tracking
  • Batch Operations - Upload multiple files simultaneously with batch progress tracking
  • Retry Mechanism - Built-in retry with exponential backoff for failed uploads
  • File Management - Get, list, delete files with full metadata support
  • TypeScript Ready - Full TypeScript support with comprehensive type definitions
  • TanStack Query Integration - Built on TanStack Query for powerful caching and state management
  • Drag & Drop Support - Built-in file input hooks with drag & drop functionality
  • Paste Upload - Support for pasting images from clipboard
  • Transform Support - Transform files and metadata on upload
  • Abort Control - Cancel uploads at any time with abort functionality

Upload Methods

Multipart Upload

Traditional multipart/form-data uploads, perfect for small to medium files and web forms.

import { useUpload } from "@visulima/storage-client/react";

const { upload, progress, isUploading } = useUpload({
    endpointMultipart: "/api/upload/multipart",
});

await upload(file);

TUS Upload

Resumable uploads using the TUS protocol, ideal for large files and unreliable networks.

import { useTusUpload } from "@visulima/storage-client/react";

const { upload, pause, resume, progress } = useTusUpload({
    endpointTus: "/api/upload/tus",
});

await upload(file);
// Can pause and resume later
pause();
resume();

Chunked REST Upload

Client-side chunked uploads for large files without requiring TUS server support.

import { useChunkedRestUpload } from "@visulima/storage-client/react";

const { upload, progress } = useChunkedRestUpload({
    endpointChunkedRest: "/api/upload/chunked-rest",
    chunkSize: 5 * 1024 * 1024, // 5MB chunks
});

await upload(file);

Quick Start

React

import { useUpload } from "@visulima/storage-client/react";

function UploadComponent() {
    const { upload, progress, isUploading, error, result } = useUpload({
        endpointMultipart: "/api/upload/multipart",
        onProgress: (progress) => console.log(`Upload: ${progress}%`),
        onSuccess: (file) => console.log("Upload complete:", file.id),
    });

    const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
        const file = e.target.files?.[0];
        if (file) {
            await upload(file);
        }
    };

    return (
        <div>
            <input type="file" onChange={handleFileChange} />
            {isUploading && <div>Progress: {progress}%</div>}
            {error && <div>Error: {error.message}</div>}
            {result && <div>File ID: {result.id}</div>}
        </div>
    );
}

Vue / Nuxt

<template>
    <div>
        <input type="file" @change="handleFileChange" />
        <div v-if="isUploading">Progress: {{ progress }}%</div>
        <div v-if="error">Error: {{ error.message }}</div>
        <div v-if="result">File ID: {{ result.id }}</div>
    </div>
</template>

<script setup lang="ts">
import { useUpload } from "@visulima/storage-client/vue";

const { upload, progress, isUploading, error, result } = useUpload({
    endpointMultipart: "/api/upload/multipart",
});

const handleFileChange = async (e: Event) => {
    const target = e.target as HTMLInputElement;
    const file = target.files?.[0];
    if (file) {
        await upload(file);
    }
};
</script>

Solid

import { createUpload } from "@visulima/storage-client/solid";

function UploadComponent() {
    const { upload, progress, isUploading, error, result } = createUpload({
        endpointMultipart: "/api/upload/multipart",
    });

    const handleFileChange = async (e: Event) => {
        const target = e.target as HTMLInputElement;
        const file = target.files?.[0];
        if (file) {
            await upload(file);
        }
    };

    return (
        <div>
            <input type="file" onChange={handleFileChange} />
            {isUploading() && <div>Progress: {progress()}%</div>}
            {error() && <div>Error: {error()?.message}</div>}
            {result() && <div>File ID: {result()?.id}</div>}
        </div>
    );
}

Svelte

<script lang="ts">
  import { createUpload } from "@visulima/storage-client/svelte";

  const { upload, progress, isUploading, error, result } = createUpload({
    endpointMultipart: "/api/upload/multipart",
  });

  async function handleFileChange(e: Event) {
    const target = e.target as HTMLInputElement;
    const file = target.files?.[0];
    if (file) {
      await upload(file);
    }
  }
</script>

<div>
  <input type="file" on:change={handleFileChange} />
  {#if $isUploading}
    <div>Progress: {$progress}%</div>
  {/if}
  {#if $error}
    <div>Error: {$error.message}</div>
  {/if}
  {#if $result}
    <div>File ID: {$result.id}</div>
  {/if}
</div>

What's Next?

Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues