Skip to content
Storage

可续传上传

Learn how to upload files to Supabase Storage.

建议在以下情况使用可续传上传方式:

🌐 The resumable upload method is recommended when:

  • 上传可能超过6MB的大文件
  • 网络稳定性是个问题
  • 你想在上传时有进度事件

Supabase Storage 实现了 TUS 协议 来支持可恢复的上传。TUS 代表 The Upload Server,是一个支持可恢复上传的开放协议。该协议允许在上传过程中断时从中断的地方继续上传。这个方法可以用 tus-js-client 库来实现,或者用其他支持 TUS 协议的客户端库,比如 Uppy。

🌐 Supabase Storage implements the TUS protocol to enable resumable uploads. TUS stands for The Upload Server and is an open protocol for supporting resumable uploads. The protocol allows the upload process to be resumed from where it left off in case of interruptions. This method can be implemented using the tus-js-client library, or other client-side libraries like Uppy that support the TUS protocol.

这里有一个使用 tus-js-client 上传文件的示例:

1
const tus = require('tus-js-client')
2
3
const projectId = ''
4
5
async function uploadFile(bucketName, fileName, file) {
6
const { data: { session } } = await supabase.auth.getSession()
7
8
return new Promise((resolve, reject) => {
9
var upload = new tus.Upload(file, {
10
// Supabase TUS endpoint (with direct storage hostname)
11
endpoint: `https://${projectId}.storage.supabase.co/storage/v1/upload/resumable`,
12
retryDelays: [0, 3000, 5000, 10000, 20000],
13
headers: {
14
authorization: `Bearer ${session.access_token}`,
15
'x-upsert': 'true', // optionally set upsert to true to overwrite existing files
16
},
17
uploadDataDuringCreation: true,
18
removeFingerprintOnSuccess: true, // Important if you want to allow re-uploading the same file https://github.com/tus/tus-js-client/blob/main/docs/api.md#removefingerprintonsuccess
19
metadata: {
20
bucketName: bucketName,
21
objectName: fileName,
22
contentType: 'image/png',
23
cacheControl: '3600',
24
metadata: JSON.stringify({ // custom metadata passed to the user_metadata column
25
yourCustomMetadata: true,
26
}),
27
},
28
chunkSize: 6 * 1024 * 1024, // NOTE: it must be set to 6MB (for now) do not change it
29
onError: function (error) {
30
console.log('Failed because: ' + error)
31
reject(error)
32
},
33
onProgress: function (bytesUploaded, bytesTotal) {
34
var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2)
35
console.log(bytesUploaded, bytesTotal, percentage + '%')
36
},
37
onSuccess: function () {
38
console.log('Download %s from %s', upload.file.name, upload.url)
39
resolve()
40
},
41
})
42
43
44
// Check if there are any previous uploads to continue.
45
return upload.findPreviousUploads().then(function (previousUploads) {
46
// Found previous uploads so we select the first one.
47
if (previousUploads.length) {
48
upload.resumeFromPreviousUpload(previousUploads[0])
49
}
50
51
// Start the upload
52
upload.start()
53
})
54
})
55
}

上传网址 #

🌐 Upload URL

在使用可续传上传端点上传时,存储服务器会为每个上传创建一个唯一的 URL,即使是对同一路径的多次上传也是如此。所有数据块都会使用 PATCH 方法上传到这个 URL。

🌐 When uploading using the resumable upload endpoint, the storage server creates a unique URL for each upload, even for multiple uploads to the same path. All chunks will be uploaded to this URL using the PATCH method.

这个唯一的上传链接有效期为 最多24小时。如果在24小时内没有完成上传,链接将会过期,你需要重新开始上传。TUS 客户端库通常会在上一个链接过期时生成一个新链接。

🌐 This unique upload URL will be valid for up to 24 hours. If the upload is not completed within 24 hours, the URL will expire and you'll need to start the upload again. TUS client libraries typically create a new URL if the previous one expires.

并发 #

🌐 Concurrency

当两个或更多的客户端上传到同一个上传 URL 时,只有其中一个会成功。其他客户端会收到 409 Conflict 错误。同一时间只能有 1 个客户端上传到同一个上传 URL,这样可以防止数据损坏。

🌐 When two or more clients upload to the same upload URL only one of them will succeed. The other clients will receive a 409 Conflict error. Only 1 client can upload to the same upload URL at a time which prevents data corruption.

当两个或更多客户端使用不同的上传 URL 上传文件到同一路径时,第一个完成上传的客户端会成功,其他客户端会收到 409 Conflict 错误。

🌐 When two or more clients upload a file to the same path using different upload URLs, the first client to complete the upload will succeed and the other clients will receive a 409 Conflict error.

如果你提供 x-upsert 头,最后一个完成上传的客户端反而会成功。

🌐 If you provide the x-upsert header the last client to complete the upload will succeed instead.

Uppy 示例 #

🌐 Uppy example

你可以查看一个【使用 Uppy 的完整示例】(https://github.com/supabase/supabase/tree/master/examples/storage/resumable-upload-uppy)。

🌐 You can check a full example using Uppy.

Uppy有与不同框架的集成:

🌐 Uppy has integrations with different frameworks:

预签名上传 #

🌐 Presigned uploads

可续传上传还支持使用签名上传令牌来创建限时 URL,你可以通过在 SDK 上调用 createSignedUploadUrl 方法并在可续传上传的 x-signature 头中包含返回的令牌与用户分享这些 URL。

🌐 Resumable uploads also supports using signed upload tokens to created time-limited URLs that you can share to your users by invoking the createSignedUploadUrl method on the SDK and including the returned token in the x-signature header of the resumable upload.

1
// Create a signed upload URL
2
const { data } = await supabase.storage.from('bucket_name').createSignedUploadUrl('file_path', {
3
upsert: true, // Optional: allow overwriting existing files
4
})
5
6
// Use the signed URL token in resumable upload headers
7
// Include data.token in the x-signature header

查看这个 使用带签名 URL 的 Uppy 完整示例 了解更多内容。

🌐 See this full example using Uppy with signed URLs for more context.

正在覆盖文件 #

🌐 Overwriting files

当上传文件到已存在的路径时,默认行为是返回 400 Asset Already Exists 错误。如果你想覆盖特定路径上的文件,可以将 x-upsert 头设置为 true。

🌐 When uploading a file to a path that already exists, the default behavior is to return a 400 Asset Already Exists error. If you want to overwrite a file on a specific path you can set the x-upsert header to true.

我们建议尽量不要覆盖文件,因为 CDN 需要一些时间将更改传播到所有边缘节点,这可能导致内容过时。上传文件到一个新的路径是避免传播延迟和内容过时的推荐方式。

🌐 We do advise against overwriting files when possible, as the CDN will take some time to propagate the changes to all the edge nodes leading to stale content. Uploading a file to a new path is the recommended way to avoid propagation delays and stale content.

想了解更多,请查看CDN指南。

🌐 To learn more, see the CDN guide.