convex-file-storage

安装量: 1.3K
排名: #1071

安装

npx skills add https://github.com/waynesutton/convexskills --skill convex file storage

Convex File Storage

Handle file uploads, storage, serving, and management in Convex applications with proper patterns for images, documents, and generated files.

Documentation Sources

Before implementing, do not assume; fetch the latest documentation:

Primary: https://docs.convex.dev/file-storage Upload Files: https://docs.convex.dev/file-storage/upload-files Serve Files: https://docs.convex.dev/file-storage/serve-files For broader context: https://docs.convex.dev/llms.txt Instructions File Storage Overview

Convex provides built-in file storage with:

Automatic URL generation for serving files Support for any file type (images, PDFs, videos, etc.) File metadata via the _storage system table Integration with mutations and actions Generating Upload URLs // convex/files.ts import { mutation } from "./_generated/server"; import { v } from "convex/values";

export const generateUploadUrl = mutation({ args: {}, returns: v.string(), handler: async (ctx) => { return await ctx.storage.generateUploadUrl(); }, });

Client-Side Upload // React component import { useMutation } from "convex/react"; import { api } from "../convex/_generated/api"; import { useState } from "react";

function FileUploader() { const generateUploadUrl = useMutation(api.files.generateUploadUrl); const saveFile = useMutation(api.files.saveFile); const [uploading, setUploading] = useState(false);

const handleUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return;

setUploading(true);
try {
  // Step 1: Get upload URL
  const uploadUrl = await generateUploadUrl();

  // Step 2: Upload file to storage
  const result = await fetch(uploadUrl, {
    method: "POST",
    headers: { "Content-Type": file.type },
    body: file,
  });

  const { storageId } = await result.json();

  // Step 3: Save file reference to database
  await saveFile({
    storageId,
    fileName: file.name,
    fileType: file.type,
    fileSize: file.size,
  });
} finally {
  setUploading(false);
}

};

return (

{uploading &&

Uploading...

}
); }

Saving File References // convex/files.ts import { mutation, query } from "./_generated/server"; import { v } from "convex/values";

export const saveFile = mutation({ args: { storageId: v.id("_storage"), fileName: v.string(), fileType: v.string(), fileSize: v.number(), }, returns: v.id("files"), handler: async (ctx, args) => { return await ctx.db.insert("files", { storageId: args.storageId, fileName: args.fileName, fileType: args.fileType, fileSize: args.fileSize, uploadedAt: Date.now(), }); }, });

Serving Files via URL // convex/files.ts export const getFileUrl = query({ args: { storageId: v.id("_storage") }, returns: v.union(v.string(), v.null()), handler: async (ctx, args) => { return await ctx.storage.getUrl(args.storageId); }, });

// Get file with URL export const getFile = query({ args: { fileId: v.id("files") }, returns: v.union( v.object({ _id: v.id("files"), fileName: v.string(), fileType: v.string(), fileSize: v.number(), url: v.union(v.string(), v.null()), }), v.null() ), handler: async (ctx, args) => { const file = await ctx.db.get(args.fileId); if (!file) return null;

const url = await ctx.storage.getUrl(file.storageId);

return {
  _id: file._id,
  fileName: file.fileName,
  fileType: file.fileType,
  fileSize: file.fileSize,
  url,
};

}, });

Displaying Files in React import { useQuery } from "convex/react"; import { api } from "../convex/_generated/api";

function FileDisplay({ fileId }: { fileId: Id<"files"> }) { const file = useQuery(api.files.getFile, { fileId });

if (!file) return

Loading...
; if (!file.url) return
File not found
;

// Handle different file types if (file.fileType.startsWith("image/")) { return {file.fileName}; }

if (file.fileType === "application/pdf") { return (