使用Uppy+Supabase实现断点续传时遇对象名非法字符错误
使用Uppy + Supabase 上传文件时提示“对象名称包含无效字符”
问题详情
我在Web应用中尝试用Uppy结合Supabase实现文件上传功能,跟着教程写了代码,但上传时一直报错:
"error": "Invalid Input", "message": "The object name contains invalid characters"
试过教程代码,也试过Supabase官方提供的Uppy示例代码,结果完全一样。已经测试过test.png、image.jpeg这类简单文件名的文件,还是无法上传。
我的代码
"use client"; import React, { useEffect, useState } from "react"; import Uppy from "@uppy/core"; import { Dashboard } from "@uppy/react"; import Tus from "@uppy/tus"; import "@uppy/core/dist/style.min.css"; import "@uppy/dashboard/dist/style.min.css"; import { createBrowserClient } from "@supabase/ssr"; function ImagesDragzone() { const [images, setImages] = useState<any[]>([]); const [loading, setIsLoading] = useState(false); const [error, setError] = useState<any>(null); const SUPABASE_ANON_KEY = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; const SUPABASE_PROJECT_ID = "vopvzwbjhdsvhnwvluwb"; const STORAGE_BUCKET = "library"; const BEARER_TOKEN = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; const supabaseStorageURL = `https://${SUPABASE_PROJECT_ID}.supabase.co/storage/v1/object/public/`; const supabase = createBrowserClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! ); var uppy = new Uppy().use(Tus, { endpoint: supabaseStorageURL, headers: { authorization: `Bearer ${BEARER_TOKEN}`, apikey: SUPABASE_ANON_KEY as string, }, uploadDataDuringCreation: true, chunkSize: 6 * 1024 * 1024, allowedMetaFields: [ "bucketName", "objectName", "contentType", "cacheControl", ], }); useEffect(() => { getBucket(); uppy.on("file-added", (file) => { const supabaseMetadata = { bucketName: STORAGE_BUCKET, objectName: file.name, contentType: file.type, }; file.meta = { ...file.meta, ...supabaseMetadata, }; console.log("file added", file); }); uppy.on("complete", (result) => { console.log( "Upload complete! We’ve uploaded these files:", result.successful ); }); }, []); async function getBucket() { setIsLoading(true); const { data, error } = await supabase.storage.from("library").list(); // console.log(data); // console.log(error); if (error) { setError(error); } else { setImages(data); } setIsLoading(false); } return ( <div> <h1>Image Showcase</h1> {error && <div>errror</div>} <div> <Dashboard uppy={uppy} showProgressDetails={true} /> </div> {loading && <div>Loading...</div>} {!loading && images.length > 0 && ( <> <h1>My images</h1> <ul> {images.map((image) => ( <li key={image.name}>{/* uploaded image here */}</li> ))} </ul> </> )} </div> ); } export default ImagesDragzone;
解决方案
核心问题
你的Tus上传端点完全写错了。Supabase的Tus断点续传上传有专门的接口地址,不是你当前使用的对象访问URL。你用的object/public/路径是用来读取已上传文件的,不是上传接口,这才导致了“无效字符”的错误提示(实际上是接口解析请求时出错)。
具体修改步骤
- 修正上传端点
把supabaseStorageURL改成Supabase官方指定的Tus上传地址:
const supabaseStorageURL = `https://${SUPABASE_PROJECT_ID}.supabase.co/storage/v1/upload/resumable`;
- 添加Uppy实例清理逻辑
组件卸载时关闭Uppy实例,避免内存泄漏:
useEffect(() => { // ... 原有代码 return () => { uppy.close(); }; }, []);
- 文件名安全处理(可选但推荐)
即使你用了简单文件名,也可以添加一次字符过滤,避免潜在的特殊字符问题:
uppy.on("file-added", (file) => { // 过滤文件名中的非法字符,只保留字母、数字、._- const sanitizedFileName = file.name.replace(/[^a-zA-Z0-9._-]/g, '_'); const supabaseMetadata = { bucketName: STORAGE_BUCKET, objectName: sanitizedFileName, contentType: file.type, }; file.meta = { ...file.meta, ...supabaseMetadata, }; });
- 上传完成后刷新文件列表
在complete事件里调用getBucket(),让上传的文件立刻显示出来:
uppy.on("complete", (result) => { console.log("Upload complete! We’ve uploaded these files:", result.successful); getBucket(); });
修改后的关键代码片段
// 修正后的上传端点 const supabaseStorageURL = `https://${SUPABASE_PROJECT_ID}.supabase.co/storage/v1/upload/resumable`; var uppy = new Uppy().use(Tus, { endpoint: supabaseStorageURL, headers: { authorization: `Bearer ${BEARER_TOKEN}`, apikey: SUPABASE_ANON_KEY as string, }, uploadDataDuringCreation: true, chunkSize: 6 * 1024 * 1024, allowedMetaFields: [ "bucketName", "objectName", "contentType", "cacheControl", ], }); useEffect(() => { getBucket(); uppy.on("file-added", (file) => { const sanitizedFileName = file.name.replace(/[^a-zA-Z0-9._-]/g, '_'); const supabaseMetadata = { bucketName: STORAGE_BUCKET, objectName: sanitizedFileName, contentType: file.type, }; file.meta = { ...file.meta, ...supabaseMetadata, }; }); uppy.on("complete", (result) => { console.log("Upload complete! We’ve uploaded these files:", result.successful); getBucket(); }); return () => { uppy.close(); }; }, []);
完成以上修改后,就能正常上传文件了。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

