You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: aspnetcore/blazor/advanced-scenarios.md
+278
Original file line number
Diff line number
Diff line change
@@ -209,3 +209,281 @@ This is a trivial example. In more realistic cases with complex and deeply neste
209
209
* Don't write long blocks of manually-implemented `RenderTreeBuilder` logic. Prefer *.razor* files and allow the compiler to deal with the sequence numbers. If you're unable to avoid manual `RenderTreeBuilder` logic, split long blocks of code into smaller pieces wrapped in `OpenRegion`/`CloseRegion` calls. Each region has its own separate space of sequence numbers, so you can restart from zero (or any other arbitrary number) inside each region.
210
210
* If sequence numbers are hardcoded, the diff algorithm only requires that sequence numbers increase in value. The initial value and gaps are irrelevant. One legitimate option is to use the code line number as the sequence number, or start from zero and increase by ones or hundreds (or any preferred interval).
211
211
* Blazor uses sequence numbers, while other tree-diffing UI frameworks don't use them. Diffing is far faster when sequence numbers are used, and Blazor has the advantage of a compile step that deals with sequence numbers automatically for developers authoring *.razor* files.
212
+
213
+
## Perform large data transfers in Blazor Server apps
214
+
215
+
In some scenarios, large amounts of data must be transferred between JavaScript and Blazor. Typically, large data transfers occur when:
216
+
217
+
* Browser file system APIs are used to upload or download a file.
218
+
* Interop with a third party library is required.
219
+
220
+
In Blazor Server, a limitation is in place to prevent passing single large messages that may result in performance issues.
221
+
222
+
Consider the following guidance when developing code that transfers data between JavaScript and Blazor:
223
+
224
+
* Slice the data into smaller pieces, and send the data segments sequentially until all of the data is received by the server.
225
+
* Don't allocate large objects in JavaScript and C# code.
226
+
* Don't block the main UI thread for long periods when sending or receiving data.
227
+
* Free any memory consumed when the process is completed or cancelled.
228
+
* Enforce the following additional requirements for security purposes:
229
+
* Declare the maximum file or data size that can be passed.
230
+
* Declare the minimum upload rate from the client to the server.
231
+
* After the data is received by the server, the data can be:
232
+
* Temporarily stored in a memory buffer until all of the segments are collected.
233
+
* Consumed immediately. For example, the data can be stored immediately in a database or written to disk as each segment is received.
234
+
235
+
The following file uploader class handles JS interop with the client. The uploader class uses JS interop to:
* The `_maxBase64SegmentSize` is set to `8192`, which is calculated from `_maxBase64SegmentSize = _segmentSize * 4 / 3`.
328
+
* Low-level .NET Core memory management APIs are used to store the memory segments on the server in `_uploadedSegments`.
329
+
* A `ReceiveFile` method is used to handle the upload through JS interop:
330
+
* The file size is determined in bytes through JS interop with `_jsRuntime.InvokeAsync<FileInfo>('getFileSize', selector)`.
331
+
* The number of segments to receive are calculated and stored in `numberOfSegments`.
332
+
* The segments are requested in a `for` loop through JS interop with `_jsRuntime.InvokeAsync<string>('receiveSegment', i, selector)`. All segments but the last must be 8,192 bytes before decoding. The client is forced to send the data in an efficient manner.
333
+
* For each segment received, checks are performed before decoding with <xref:System.Convert.TryFromBase64String*>.
334
+
* A stream with the data is returned as a new <xref:System.IO.Stream> (`SegmentedStream`) after the upload is complete.
335
+
336
+
The segmented stream class exposes the list of segments as a readonly non-seekable <xref:System.IO.Stream>:
0 commit comments