Skip to content

Commit f71e8a4

Browse files
committed
feat: docs for sdk multipart
1 parent 5109d5e commit f71e8a4

File tree

3 files changed

+131
-9
lines changed

3 files changed

+131
-9
lines changed

docs/sdks/tigris/client-uploads.mdx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ import { upload } from "@tigrisdata/storage/client";
3838
| onUploadProgress | No | Callback to track upload progress: `onUploadProgress({loaded: number, total: number, percentage: number})`. |
3939
| config | No | A configuration object to override the [default configuration](/docs/sdks/tigris/using-sdk#authentication). |
4040

41+
In case of successful upload, the `data` property will be set to the upload and
42+
contains the following properties:
43+
44+
- `contentDisposition`: content disposition of the object
45+
- `contentType`: content type of the object
46+
- `modified`: Last modified date of the object
47+
- `path`: Path to the object
48+
- `size`: Size of the object
49+
- `url`: A presigned URL to the object
50+
4151
### Example
4252

4353
```html
@@ -49,6 +59,7 @@ import { upload } from "@tigrisdata/storage/client";
4959
upload("file.txt", file, {
5060
url: "/api/upload",
5161
access: "private",
62+
multipart: true,
5263
onUploadProgress: ({ loaded, total, percentage }) => {
5364
console.log(`Uploaded ${loaded} of ${total} bytes (${percentage}%)`);
5465
},

docs/sdks/tigris/examples.mdx

Lines changed: 117 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ some ready examples available at
99
Something missing there that you you'd like to see? Let us know and we'll be
1010
more than happy to add in examples.
1111

12-
### Viewing and downloading files
12+
## Viewing and downloading files
1313

1414
`get` function can be used to get a file from a bucket. `contentDisposition`
1515
option can be to either `attachment` or `inline` depending on whether you want
@@ -82,7 +82,7 @@ export default function Avatar() {
8282

8383
To trigger a download, set the `contentDisposition` option to `attachment`.
8484

85-
### Uploading files
85+
## Uploading files
8686

8787
`put` function can be used to upload a file to a bucket.
8888

@@ -140,7 +140,7 @@ export default function Upload() {
140140
</TabItem>
141141
</Tabs>
142142

143-
### Client Uploads
143+
## Client Uploads
144144

145145
Tigris does not charge egress fees, but your hosting provider may charge them
146146
for user uploads to Tigris. We care about your bandwidth costs, so we made it
@@ -152,6 +152,118 @@ We leverage the
152152
[presigned URLs](/docs/sdks/tigris/using-sdk#presigning-an-object) features to
153153
allow you to upload files directly to Tigris from the client side.
154154

155+
### Multipart upload
156+
157+
<Tabs>
158+
<TabItem value="server" label="Server" default>
159+
160+
```ts
161+
// app/api/upload/route.ts
162+
import { NextRequest, NextResponse } from "next/server";
163+
import {
164+
initMultipartUpload,
165+
getPartsPresignedUrls,
166+
completeMultipartUpload,
167+
UploadAction,
168+
} from "@tigrisdata/storage";
169+
170+
export async function POST(request: NextRequest) {
171+
try {
172+
const { path, operation, action, contentType, uploadId, parts, partIds } =
173+
await request.json();
174+
175+
switch (action) {
176+
case UploadAction.MultipartInit: {
177+
const result = await initMultipartUpload(path, {});
178+
return NextResponse.json({ data: result.data });
179+
}
180+
181+
case UploadAction.MultipartParts: {
182+
if (!uploadId || !parts) {
183+
return NextResponse.json(
184+
{ error: "uploadId and parts are required for multipart-parts" },
185+
{ status: 400 },
186+
);
187+
}
188+
const result = await getPartsPresignedUrls(path, parts, uploadId, {});
189+
return NextResponse.json({ data: result.data });
190+
}
191+
192+
case UploadAction.MultipartComplete: {
193+
if (!uploadId) {
194+
return NextResponse.json(
195+
{ error: "uploadId is required for multipart-complete" },
196+
{ status: 400 },
197+
);
198+
}
199+
const result = await completeMultipartUpload(path, uploadId, partIds);
200+
return NextResponse.json({ data: result.data });
201+
}
202+
203+
default:
204+
return NextResponse.json(
205+
{ error: `Unsupported operation: ${operation}` },
206+
{ status: 400 },
207+
);
208+
}
209+
} catch (error) {
210+
return NextResponse.json(
211+
{ error: "Failed to process upload request" },
212+
{ status: 500 },
213+
);
214+
}
215+
}
216+
```
217+
218+
</TabItem>
219+
220+
<TabItem value="client" label="Client">
221+
222+
```tsx
223+
"use client";
224+
225+
import { upload } from "@tigrisdata/storage/client";
226+
import { useState } from "react";
227+
228+
export default function ClientUpload() {
229+
const [progress, setProgress] = useState<number>(0);
230+
const [url, setUrl] = useState<string | null>(null);
231+
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
232+
const file = e.target.files?.[0];
233+
setProgress(0);
234+
if (file) {
235+
const result = await upload(`${file.name}`, file, {
236+
url: "/api/upload",
237+
access: "private",
238+
multipart: true,
239+
partSize: 10 * 1024 * 1024, // 10 MiB parts
240+
onUploadProgress: ({ loaded, total, percentage }) => {
241+
setProgress(percentage);
242+
if (percentage === 100) {
243+
setProgress(0);
244+
}
245+
},
246+
});
247+
setUrl(result.url);
248+
}
249+
};
250+
251+
return (
252+
<>
253+
<input type="file" onChange={handleFileChange} />{" "}
254+
{url && <div>Uploaded to: {url}</div>}{" "}
255+
{progress > 0 && progress < 100 && <div>{progress}%</div>}{" "}
256+
</>
257+
);
258+
}
259+
```
260+
261+
</TabItem>
262+
263+
</Tabs>
264+
265+
### Simple upload
266+
155267
<Tabs>
156268
<TabItem value="server" label="Server" default>
157269

@@ -162,10 +274,9 @@ import { getPresignedUrl } from "@tigrisdata/storage";
162274

163275
export async function POST(request: NextRequest) {
164276
try {
165-
const { path, method, contentType } = await request.json();
277+
const { path, contentType } = await request.json();
166278
const result = await getPresignedUrl(path, {
167-
method,
168-
contentType,
279+
operation: "put",
169280
expiresIn: 3600, // 1 hour
170281
});
171282

docs/sdks/tigris/using-sdk.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ getPresignedUrl(path: string, options: GetPresignedUrlOptions): Promise<TigrisSt
365365

366366
| **Parameter** | **Required** | **Values** |
367367
| ------------- | ------------ | ---------------------------------------------------------------------------------------- |
368-
| method | No | Specify the operation to use for the presigned URL. Possible values are `get` and `put`. |
368+
| operation | No | Specify the operation to use for the presigned URL. Possible values are `get` and `put`. |
369369
| expiresIn | No | The expiration time of the presigned URL in seconds. Default is 3600 seconds (1 hour). |
370370
| contentType | No | The content type of the object. |
371371
| config | No | A configuration object to override the [default configuration](#authentication). |
@@ -382,7 +382,7 @@ presigned URL and contains the following properties:
382382
#### Get a presigned URL for a GET operation
383383

384384
```ts
385-
const result = await getPresignedUrl("object.txt", { method: "get" });
385+
const result = await getPresignedUrl("object.txt", { operation: "get" });
386386

387387
if (result.error) {
388388
console.error("Error getting presigned URL:", result.error);
@@ -394,7 +394,7 @@ if (result.error) {
394394
#### Get a presigned URL for a PUT operation
395395

396396
```ts
397-
const result = await getPresignedUrl("object.txt", { method: "put" });
397+
const result = await getPresignedUrl("object.txt", { operation: "put" });
398398
```
399399

400400
## Listing objects

0 commit comments

Comments
 (0)