Skip to content

Commit f641d5e

Browse files
authored
feat: signed upload URL upsert (#199)
1 parent adb58bb commit f641d5e

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

infra/storage/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
FROM supabase/storage-api:v1.0.10
1+
FROM supabase/storage-api:v1.2.1
22

33
RUN apk add curl --no-cache

src/packages/StorageFileApi.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,11 @@ export default class StorageFileApi {
220220
* Signed upload URLs can be used to upload files to the bucket without further authentication.
221221
* They are valid for 2 hours.
222222
* @param path The file path, including the current file name. For example `folder/image.png`.
223+
* @param options.upsert If set to true, allows the file to be overwritten if it already exists.
223224
*/
224225
async createSignedUploadUrl(
225-
path: string
226+
path: string,
227+
options?: { upsert: boolean }
226228
): Promise<
227229
| {
228230
data: { signedUrl: string; token: string; path: string }
@@ -236,11 +238,17 @@ export default class StorageFileApi {
236238
try {
237239
let _path = this._getFinalPath(path)
238240

241+
const headers = { ...this.headers }
242+
243+
if (options?.upsert) {
244+
headers['x-upsert'] = 'true'
245+
}
246+
239247
const data = await post(
240248
this.fetch,
241249
`${this.url}/object/upload/sign/${_path}`,
242250
{},
243-
{ headers: this.headers }
251+
{ headers }
244252
)
245253

246254
const url = new URL(this.url + data.url)

test/storageFileApi.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,26 @@ describe('Object API', () => {
242242
expect(uploadRes.data?.path).toEqual(uploadPath)
243243
})
244244

245+
test('can upload overwriting files with a signed url', async () => {
246+
const { error: uploadErr } = await storage.from(bucketName).upload(uploadPath, file)
247+
248+
expect(uploadErr).toBeNull()
249+
250+
const { data, error } = await storage.from(bucketName).createSignedUploadUrl(uploadPath, {
251+
upsert: true,
252+
})
253+
254+
expect(error).toBeNull()
255+
assert(data?.path)
256+
257+
const uploadRes = await storage
258+
.from(bucketName)
259+
.uploadToSignedUrl(data.path, data.token, file)
260+
261+
expect(uploadRes.error).toBeNull()
262+
expect(uploadRes.data?.path).toEqual(uploadPath)
263+
})
264+
245265
test('cannot upload to a signed url twice', async () => {
246266
const { data, error } = await storage.from(bucketName).createSignedUploadUrl(uploadPath)
247267

@@ -258,6 +278,7 @@ describe('Object API', () => {
258278
const uploadRes2 = await storage
259279
.from(bucketName)
260280
.uploadToSignedUrl(data.path, data.token, file)
281+
261282
expect(uploadRes2.error).toEqual({
262283
error: 'Duplicate',
263284
message: 'The resource already exists',

0 commit comments

Comments
 (0)