How to Build a Complete File-Sharing Application Using Filestack
File sharing is a common requirement across many types of applications, from internal tools and clie 2026-7-30 21:5:49 Author: hackernoon.com(查看原文) 阅读量:22 收藏

File sharing is a common requirement across many types of applications, from internal tools and client portals to full-featured SaaS products. While the concept is straightforward, implementing it well requires handling uploads, generating shareable links, delivering files globally, and optionally supporting real-time image transformations.

This guide walks through building a complete file-sharing application using Filestack for uploads, storage, CDN delivery, and image processing.

What We’re Building

A user visits your app, drops a file, and gets back a short link. Anyone with that link can preview, download, or view the file. If the file is an image, they can apply transformations like blur, crop, grayscale, and rounded corners, then copy the transformed URL, all without any server-side image processing code.

What you’ll have at the end:

  • Drag-and-drop file upload with real-time progress
  • Unique shareable short link per file
  • Image previews with on-the-fly transformations

Stack

Layer

Technology

Framework

Next.js (App Router)

File upload & CDN

Filestack

Database

Turso (edge SQLite)

ORM

Drizzle ORM

Language

TypeScript

If you don’t want to use Turso, any SQL database works. The schema is a single table.

Step 1: Get Your Filestack API Key

Sign up at Filestack (there’s a generous free tier). Once you have an account, grab your API key from the dashboard. If you’re new to Filestack, the Quick Start guide walks you through the basics in a few minutes.

NEXT_PUBLIC_FILESTACK_API_KEY=your_api_key_here


Filestack handlesstorage on S3 and serves files through a global CDN. You don’t configure buckets or manage infrastructure. It just works.

Step 2: Set Up Your Database

We’re using Turso, a distributed SQLite database that runs at the edge. In development, it uses a local .dbfile, so there’s no cloud setup needed to get started. Follow the Turso quickstart to get set up, then add your credentials to your environment:

TURSO_DATABASE_URL=libsql://your-db.turso.io

TURSO_AUTH_TOKEN=your-auth-token

Once that’s done, define the schema. You only need one table:

// lib/db/schema.ts

import { sqliteTable, text, integer, index } from "drizzle-orm/sqlite-core";



export const shares = sqliteTable(

  "shares",

  {

    id:          text("id").primaryKey(),

    code:        text("code").notNull().unique(),      // The short URL code /s/abc123

    handle:      text("handle").notNull(),             // Filestack file handle

    url:         text("url").notNull(),                // Full Filestack CDN URL

    filename:    text("filename").notNull(),

    mimetype:    text("mimetype").notNull(),

    size:        integer("size").notNull(),

    views:       integer("views").notNull().default(0),

    createdAt:   integer("created_at").notNull(),      // Unix ms timestamp

    fingerprint: text("fingerprint").notNull().default(""),

  },

  (t) => [

    index("shares_code_idx").on(t.code),

    index("shares_fingerprint_idx").on(t.fingerprint),

  ]

);

The equivalent SQL, if you prefer to see it plainly:

CREATE TABLE shares (

  id          TEXT PRIMARY KEY,

  code        TEXT NOT NULL UNIQUE,

  handle      TEXT NOT NULL,

  url         TEXT NOT NULL,

  filename    TEXT NOT NULL,

  mimetype    TEXT NOT NULL,

  size        INTEGER NOT NULL,

  views       INTEGER NOT NULL DEFAULT 0,

  created_at  INTEGER NOT NULL,

  fingerprint TEXT NOT NULL DEFAULT ''

);



CREATE INDEX shares_code_idx        ON shares(code);

CREATE INDEX shares_fingerprint_idx ON shares(fingerprint);

Run npx drizzle-kit push to create the table on Turso.

Step 3: Upload Files Directly to Filestack

You can use the Filestack File Picker for a drop-in upload UI, or use one of the official SDKs (JavaScript, React, Angular, Python, and more). For this project, we went with a plain XHR call to the Store API to get native progress events:

async function uploadToFilestack(

  file: File,

  apiKey: string,

  onProgress: (percent: number) => void,

) {

  return new Promise<{ url: string; filename: string; type: string; size: number }>(

    (resolve, reject) => {

      const xhr = new XMLHttpRequest();

      const params = new URLSearchParams({ key: apiKey, filename: file.name });



      xhr.open("POST", `https://www.filestackapi.com/api/store/S3?${params}`);

      xhr.setRequestHeader("Content-Type", file.type || "application/octet-stream");



      xhr.upload.onprogress = (evt) => {

        if (evt.lengthComputable) {

          onProgress(Math.round((evt.loaded / evt.total) * 100));

        }

      };



      xhr.onload = () => {

        if (xhr.status >= 200 && xhr.status < 300) {

          resolve(JSON.parse(xhr.responseText));

        } else {

          reject(new Error(`Upload failed: ${xhr.status}`));

        }

      };



      xhr.onerror = () => reject(new Error("Network error"));

      xhr.send(file);

    }

  );

}

Filestack responds with a URL like this:

https://cdn.filestackcontent.com/AbCdEfGh1234567890ab

That last segment is the handle. Save it. You’ll use it to build transformation URLs later.

function extractHandle(url: string): string {

  return url.replace("https://cdn.filestackcontent.com/", "").split("?")[0];

}

After the upload succeeds, call your own API route to save the metadata and generate a short shareable code:

// app/api/share/route.ts

import { NextResponse } from "next/server";

import { nanoid } from "nanoid";

import { db, schema } from "@/lib/db";



export async function POST(req: Request) {

  const { handle, url, filename, mimetype, size } = await req.json();



  if (!/^https:\/\/cdn\.filestackcontent\.com\//.test(url)) {

    return NextResponse.json({ error: "Invalid URL" }, { status: 400 });

  }



  const id = nanoid();

  const code = nanoid(10);



  await db.insert(schema.shares).values({

    id, code, handle, url, filename, mimetype, size,

    createdAt: Date.now(),

  });



  return NextResponse.json({ code });

}

The client then redirects the user to /s/{code}, where the share page lives.

When someone opens /s/abc123, look up the record and render the file preview:

// app/s/[code]/page.tsx

async function getShare(code: string) {

  const rows = await db

    .select()

    .from(schema.shares)

    .where(eq(schema.shares.code, code))

    .limit(1);



  return rows[0];

}

Bump the view count while you're at it:

async function bumpViews(id: string) {

  await db

    .update(schema.shares)

    .set({ views: sql`${schema.shares.views} + 1` })

    .where(eq(schema.shares.id, id));

}

For the preview itself, check the MIME type and render accordingly. Images get an <img> tag, PDFs can use Filestack’s Document Viewer, and videos get a <video> element. Filestack’s CDN handles delivery for all of them.

Step 6: On-The-Fly Image Transformations

Once a file is uploaded, you can transform it by changing the URL. No server-side image processing, no extra libraries.

Filestack’s Processing API supports resize, crop, rotate, filters, and more. Transformations are chained as URL segments:

Transformation

URL

Resize to 300px

https://cdn.filestackcontent.com/resize=width:300/HANDLE

Square crop

https://cdn.filestackcontent.com/resize=width:300,height:300,fit:crop/HANDLE

Grayscale

https://cdn.filestackcontent.com/monochrome/HANDLE

Blur

https://cdn.filestackcontent.com/blur=amount:8/HANDLE

Sepia

https://cdn.filestackcontent.com/sepia=tone:80/HANDLE

Rounded corners

https://cdn.filestackcontent.com/rounded_corners=radius:30/HANDLE

Polaroid effect

https://cdn.filestackcontent.com/polaroid/HANDLE

Rotate 90°

https://cdn.filestackcontent.com/rotate=deg:90/HANDLE

You can chain them. Here’s a grayscale, rounded-corners thumbnail in a single URL:

https://cdn.filestackcontent.com/resize=width:300/monochrome/rounded_corners=radius:30/HANDLE

Filestack also offers a Transformations UI if you want to give users a visual editor instead of building your own. And for video/audio, there’s a dedicated Video and Audio Processing API.

What Else Can You Build With This?

Once Filestack is hooked up, the same pattern can power a lot more:

Product

How

User profile avatars

Upload, crop, resize, then save the handle to the user record

E-commerce product images

Upload once, generate any size variant via the URL

Client document portal

Upload files and serve them from short, access-controlled links

Video hosting (MVP)

Upload MP4, serve directly via Filestack CDN with a <video> tag

Image-heavy blog CMS

Editors upload once, and the frontend requests the right size per breakpoint

Deploy Checklist

Before going live:

  • NEXT_PUBLIC_FILESTACK_API_KEY set in your hosting environment
  • TURSO_DATABASE_URL and TURSO_AUTH_TOKEN are set for production
  • npx drizzle-kit push run against your production Turso database
  • Filestack Security Policies are configured to restrict file types and sizes at the API level

Further Reading

If you want to go deeper, here are some good next steps:

Topic

Link

Getting started with Filestack

Quick Start

How Filestack works under the hood

How Filestack Works

File Picker (drop-in upload UI)

File Pickers

Generate a picker with no code

Picker Code Generator

All image and file transformations

Processing API Reference

Video and audio processing

Video & Audio API

AI features (tagging, OCR, virus scan)

Intelligence

Automate file workflows

Workflows

SDKs (JS, React, Python, Go, etc.)

Framework SDKs

Security and access control

Security Policies

Step-by-step tutorials

Tutorials

Blog and more use cases

Filestack Blog

Final Thoughts

The thing that makes Filestack worth using isn’t just the upload API. Once a file is uploaded, you get CDN delivery and the Processing API included. You write zero image processing code, you manage zero storage infrastructure, and you can still deliver a rich experience from a single file handle.

Try the live demo at fireshare-swart.vercel.app or grab the source code on GitHub.

Start there, strip it down to your use case, and you’ll have something production-ready faster than you’d expect.


文章来源: https://hackernoon.com/how-to-build-a-complete-file-sharing-application-using-filestack?source=rss
如有侵权请联系:admin#unsafe.sh