Skip to content

Commit cf71017

Browse files
docs(Upload): add chunk upload docs (#2968)
* docs(Upload): add chunk upload docs * chore(Upload): apply suggestions * chore(Upload): add article to overview
1 parent ee38299 commit cf71017

File tree

3 files changed

+259
-0
lines changed

3 files changed

+259
-0
lines changed

components/upload/chunk-upload.md

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
---
2+
title: Chunk Upload
3+
page_title: Chunk Upload
4+
description: Enable and configure chunk upload in Upload for Blazor.
5+
slug: upload-chunk
6+
tags: telerik,blazor,upload,chunk
7+
published: True
8+
position: 3
9+
---
10+
11+
# Chunk Upload
12+
13+
Chunk upload works by splitting a file into smaller parts (chunks) and sending them in multiple requests. These chunks are then reassembled at the remote endpoint into the final file.
14+
15+
## Basics
16+
17+
To set up the Chunk upload feature, use the `UploadChunkSettings` tag, which is nested inside `UploadSettings`. The tag includes the following parameters:
18+
19+
| Parameter | Type and Default Value | Description |
20+
|----------|----------|----------|
21+
| `AutoRetryAfter` | `double` <br/> (100) | Specifies the amount of time in milliseconds after which a failed chunk upload request will be retried.
22+
| `Enabled` | `bool` <br/> (`true`) | Specifies if the chunk upload is enabled.
23+
| `MaxAutoRetries` | `int` <br/> (1) | Specifies the number of attempts to retry uploading a failed chunk.
24+
| `MetadataField` | `string` <br/> (`chunkMetadata`) | Specifies the name of the variable that will receive the chunk upload metadata in the remote endpoint.
25+
| `Resumable` | `bool` <br/> (`true`) | Specifies if the file upload process can be paused and later resumed.
26+
| `Size` | `double` <br/> (1024 * 1024) | The size of the chunks in bytes.
27+
28+
## Events
29+
30+
The Upload exposes several relevant events. You can find related examples in the [Events](slug:upload-events) article.
31+
32+
* `OnPause`&mdash;fires when the user clicks on the pause button during chunk upload.
33+
* `OnResume`&mdash;fires when the user clicks on the "resume" button during chunk upload.
34+
35+
## Example
36+
37+
The `UploadController` class below assumes that the project name and namespace is `TelerikBlazorApp`.
38+
39+
Make sure to enable controller routing in the app startup file (`Program.cs`). In this case, `app.MapDefaultControllerRoute();` is all that's needed.
40+
41+
Also see:
42+
43+
* Section [Implement Controller Methods](slug:upload-overview#implement-controller-methods)
44+
* Page [Upload Troubleshooting](slug:upload-troubleshooting)
45+
46+
>caption Enable Chunk Upload
47+
48+
<div class="skip-repl"></div>
49+
50+
````RAZOR
51+
<TelerikUpload SaveUrl="@CustomSaveUrl"
52+
OnPause="@OnPause"
53+
OnResume="@OnResume"
54+
RemoveUrl="@RemoveUrl"
55+
AutoUpload="true">
56+
<UploadSettings>
57+
<UploadChunkSettings Size="16000"
58+
AutoRetryAfter="300"
59+
MaxAutoRetries="2"
60+
MetadataField="customChunkMetadata"
61+
Resumable="false">
62+
</UploadChunkSettings>
63+
</UploadSettings>
64+
</TelerikUpload>
65+
66+
@code {
67+
private string SaveUrl => NavigationManager.ToAbsoluteUrl("api/upload/chunksave");
68+
private string RemoveUrl => NavigationManager.ToAbsoluteUrl("api/upload/remove");
69+
private string CustomSaveUrl => NavigationManager.ToAbsoluteUrl("api/upload/chunksavecustom");
70+
71+
private void OnPause(UploadPauseEventArgs args)
72+
{
73+
Console.WriteLine("pause event");
74+
75+
foreach (var file in args.Files)
76+
{
77+
Console.WriteLine(file.Name);
78+
}
79+
}
80+
81+
private void OnResume(UploadResumeEventArgs args)
82+
{
83+
Console.WriteLine("resume event");
84+
85+
foreach (var file in args.Files)
86+
{
87+
Console.WriteLine(file.Name);
88+
}
89+
}
90+
}
91+
````
92+
````C# UploadController.cs
93+
using System;
94+
using System.IO;
95+
using System.Threading.Tasks;
96+
using Microsoft.AspNetCore.Hosting;
97+
using Microsoft.AspNetCore.Http;
98+
using Microsoft.AspNetCore.Mvc;
99+
100+
namespace TelerikBlazorApp.Controllers
101+
{
102+
[Route("api/[controller]/[action]")]
103+
public class UploadController : ControllerBase
104+
{
105+
public IWebHostEnvironment HostingEnvironment { get; set; }
106+
107+
public UploadController(IWebHostEnvironment hostingEnvironment)
108+
{
109+
HostingEnvironment = hostingEnvironment;
110+
}
111+
112+
[HttpPost]
113+
public async Task<IActionResult> ChunkSave(IEnumerable<IFormFile> files, string chunkMetadata)
114+
{
115+
foreach (var file in files)
116+
{
117+
if (file != null)
118+
{
119+
try
120+
{
121+
var rootPath = HostingEnvironment.WebRootPath; // Save to wwwroot
122+
// var rootPath = HostingEnvironment.ContentRootPath; // For saving outside wwwroot
123+
124+
var filePath = Path.Combine(rootPath, file.FileName);
125+
126+
// If chunkMetadata is provided, append chunks
127+
using (var stream = new FileStream(filePath, FileMode.Append))
128+
{
129+
await file.CopyToAsync(stream);
130+
}
131+
132+
Response.StatusCode = 201;
133+
await Response.WriteAsync("Chunk upload successful.");
134+
}
135+
catch (Exception ex)
136+
{
137+
Response.StatusCode = 500;
138+
await Response.WriteAsync($"Chunk upload failed. Exception: {ex.Message}");
139+
return new EmptyResult();
140+
}
141+
}
142+
}
143+
144+
return new EmptyResult();
145+
}
146+
147+
[HttpPost]
148+
public async Task<IActionResult> ChunkSaveCustom(IEnumerable<IFormFile> files, [FromForm(Name = "customChunkMetadata")] string customChunkMetadata)
149+
{
150+
foreach (var file in files)
151+
{
152+
if (file != null)
153+
{
154+
try
155+
{
156+
var rootPath = HostingEnvironment.WebRootPath;
157+
var filePath = Path.Combine(rootPath, file.FileName);
158+
159+
using (var stream = new FileStream(filePath, FileMode.Append))
160+
{
161+
await file.CopyToAsync(stream);
162+
}
163+
164+
Response.StatusCode = 201;
165+
await Response.WriteAsync("Custom chunk upload successful.");
166+
}
167+
catch (Exception ex)
168+
{
169+
Response.StatusCode = 500;
170+
await Response.WriteAsync($"Custom chunk upload failed. Exception: {ex.Message}");
171+
return new EmptyResult();
172+
}
173+
}
174+
}
175+
176+
return new EmptyResult();
177+
}
178+
179+
[HttpPost]
180+
public async Task<IActionResult> Remove([FromForm] string files) // "files" matches the Upload RemoveField value
181+
{
182+
bool shouldSucceed = Convert.ToBoolean(Request.Form["successData"])
183+
&& Convert.ToBoolean(Request.Headers["successHeader"]);
184+
185+
if (!shouldSucceed)
186+
{
187+
Response.StatusCode = 403;
188+
await Response.WriteAsync("Delete refused.");
189+
}
190+
else if (files != null)
191+
{
192+
try
193+
{
194+
var rootPath = HostingEnvironment.WebRootPath; // delete from wwwroot - Blazor Server only
195+
//var rootPath = HostingEnvironment.ContentRootPath; // delete from Server project root - Blazor Server or WebAssembly
196+
var fileLocation = Path.Combine(rootPath, files);
197+
198+
if (System.IO.File.Exists(fileLocation))
199+
{
200+
System.IO.File.Delete(fileLocation);
201+
202+
Response.StatusCode = 200;
203+
await Response.WriteAsync($"Delete successful.");
204+
}
205+
}
206+
catch (Exception ex)
207+
{
208+
Response.StatusCode = 500;
209+
await Response.WriteAsync($"Delete failed. Exception: {ex.Message}");
210+
}
211+
}
212+
213+
return new EmptyResult();
214+
}
215+
}
216+
}
217+
````
218+
````C# Program.cs
219+
// ...
220+
221+
var builder = WebApplication.CreateBuilder(args);
222+
223+
// ...
224+
225+
builder.Services.AddControllers();
226+
227+
var app = builder.Build();
228+
229+
// ...
230+
231+
app.MapDefaultControllerRoute();
232+
233+
// ...
234+
235+
app.Run();
236+
````
237+
238+
## See Also
239+
240+
* [Blazor Upload](slug:upload-overview)

components/upload/events.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ First, get familiar with the [**Event Arguments**](#event-arguments) section, as
1717
* [`OnCancel`](#oncancel)
1818
* [`OnClear`](#onclear)
1919
* [`OnError`](#onerror)
20+
* [`OnPause`](#onpause)
2021
* [`OnProgress`](#onprogress)
2122
* [`OnRemove`](#onremove)
23+
* [`OnResume`](#onresume)
2224
* [`OnSelect`](#onselect)
2325
* [Renaming uploaded files](#renaming-a-file)
2426
* [`OnSuccess`](#onsuccess)
@@ -179,6 +181,13 @@ public async Task<IActionResult> Save(IFormFile files)
179181

180182
See the [full example](#example) below.
181183

184+
## OnPause
185+
186+
The `OnPause` event fires when the user clicks on the pause button during chunk upload. The `UploadPauseEventArgs` event argument contains the [properties `Files` and `IsCancelled`](#event-arguments). The `Files` property can contain one or more files.
187+
188+
If you cancel the event, the chunk upload will not be paused.
189+
190+
See a full example in the [Chunk Upload article](slug:upload-chunk).
182191

183192
## OnProgress
184193

@@ -274,6 +283,13 @@ public async Task<IActionResult> Remove([FromForm] string files)
274283

275284
See the [full example](#example) below.
276285

286+
## OnResume
287+
288+
The `OnResume` event fires when the user clicks on the resume button during chunk upload. The `UploadResumeEventArgs` event argument contains the [properties `Files` and `IsCancelled`](#event-arguments). The `Files` property can contain one or more files.
289+
290+
If you cancel the event, the chunk upload will not be resumed.
291+
292+
See a full example in the [Chunk Upload article](slug:upload-chunk).
277293

278294
## OnSelect
279295

components/upload/overview.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ Authentication and authorization depends on the application.
177177

178178
[Cross-origin (CORS) requests](https://www.w3.org/TR/cors/) depend on the application and endpoint setup. The Upload [`WithCredentials` parameter](#upload-parameters) sets the corresponding [parameter of the XHR request](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials). Cookies, headers and other parameters of the Blazor app and CORS endpoint should be implemented by the respective applications (for example, set the `Access-Control-Allow-Origin` header with an appropriate value and the `Access-Control-Allow-Credentials` header with a `true` value). Read more in this [CORS Tutorial](https://www.html5rocks.com/en/tutorials/cors/). Also check [this forum thread](https://www.telerik.com/forums/upload-component-reports-'file-failed-to-upload'#-6QPJn3obkm3D1kR1ysukA), which shows one way to setup the CORS requests, headers and responses on the receiving server.
179179

180+
## Chunk Upload
181+
182+
The Upload component includes an option to upload files in chunks. [Read more about the Chunk Upload feature...](slug:upload-chunk)
180183

181184
## Validation
182185

0 commit comments

Comments
 (0)