参考手册Workspace 包参考

storage 文件存储

S3 兼容的文件存储解决方案,支持预签名 URL、直接上传和图片水印

本页是 01MVP 模板的 Workspace 包参考,适合在需要查看导出、源码入口和扩展点时使用。若你正在按功能启用或改造模板,先看 存储与文件

S3 的 Access Key 和 Secret Access Key 是敏感信息,必须放在 .env.local 中,不要提交到 Git。如果泄露了,立即去云服务商后台重置。

这是什么

@01mvp/storage 是文件存储包,基于 S3 协议兼容多种对象存储服务(AWS S3、腾讯云 COS、Cloudflare R2 等)。提供上传下载、预签名 URL 和图片水印能力。

能做什么

  • 服务端文件上传 / 下载 / 删除
  • 生成预签名 URL(Presigned URL):临时访问链接,让客户端直传文件,无需经过你的服务器中转
  • 图片水印(Logo 叠加)
  • URL 工具:把存储路径自动转成可访问的公开 URL

怎么配置

.env.local 配置 S3 兼容服务的密钥:

# 必需
S3_ENDPOINT=https://your-bucket.cos.ap-region.myqcloud.com
S3_ACCESS_KEY_ID=your-access-key-id
S3_SECRET_ACCESS_KEY=your-secret-access-key

# 可选
S3_REGION=auto                        # 存储区域,默认 "auto"
S3_PUBLIC_ENDPOINT=https://cdn.example.com  # CDN 加速域名
S3_APPID=1234567890                   # 腾讯云 COS 需要的 Appid(可选,通常从 bucket 名自动提取)

环境变量说明

Prop

Type

大概原理

前端获取上传凭证 → 客户端直传到存储服务 → 返回文件 URL
  1. 后端生成一个有时效的预签名 URL(默认 60 秒有效)
  2. 客户端拿到 URL 后直接 PUT 文件到存储服务
  3. 上传完成后用 getPublicStorageUrl 得到公开访问地址

这种方式不消耗你的服务器带宽,大文件也不拖垮服务。

快速使用

服务端生成签名 URL

import { getSignedUploadUrl } from "@01mvp/storage";

export async function POST(request: Request) {
  const { path, contentType } = await request.json();
  const signedUrl = await getSignedUploadUrl(path, {
    bucket: "my-bucket",
    contentType,
  });
  return Response.json({ signedUrl });
}

客户端直传

"use client";
import { uploadWithSignedUrlFallback } from "@01mvp/storage/client";

async function handleUpload(file: File) {
  const url = await uploadWithSignedUrlFallback({
    file,
    bucket: "my-bucket",
    path: `uploads/${Date.now()}-${file.name}`,
    contentType: file.type,
  });
  console.log("上传完成:", url);
}

客户端上传参数

uploadWithSignedUrlFallback() 接受以下参数:

Prop

Type

API 参考

  • getSignedUploadUrl(path, options) -- 生成预签名上传 URL,有效期 60 秒
  • uploadFileToS3(path, options) -- 服务端直接上传文件
  • deleteFileFromS3(path, options) -- 删除文件
  • uploadWithSignedUrlFallback(options) -- 客户端上传,预签名直传失败自动降级到服务端中转
  • getPublicStorageUrl(value, publicEndpoint?) -- 存储路径转公开 URL
  • mapPublicStorageUrls(record, keys, publicEndpoint?) -- 批量转换对象中的存储路径
  • addWatermark(imageBuffer, options?) -- 添加 Logo 水印(需 public/images/logo-white.png
  • isLogoAvailable() -- 检查 Logo 文件是否存在

最佳实践

  • 客户端上传优先用预签名 URL -- 不消耗服务器带宽
  • 始终设置 Content-Type -- 确保浏览器能正确处理文件
  • 使用 CDN 加速 -- 配置 S3_PUBLIC_ENDPOINT 指向 CDN 域名
  • 上传前验证文件类型和大小
  • 使用唯一文件名${Date.now()}-${crypto.randomUUID()}-${file.name}

故障排查

  • 预签名 URL 签名错误:确保 bucket 名称包含 APPID
  • CORS 错误:在存储桶上配置允许你的域名跨域访问
  • 水印 Logo 缺失:确认 public/images/logo-white.png 存在

相关资源