#2406 - Allow to define Http method for Upload component (#2407)

* #2406 - Allow to define Http method for Upload component

* #2406 - Allow to define Http method for Upload component and stream raw file data

* #2406 - Allow to define Http method for Upload component
Example how to stream file

---------

Co-authored-by: Pavlo Iatsiuk <pavlo.iatsiuk@nems.eco>
This commit is contained in:
Pavlo Iatsiuk
2026-01-12 08:22:15 +01:00
committed by GitHub
parent 2debdbfd38
commit 0ad1200870
6 changed files with 102 additions and 15 deletions

View File

@@ -50,7 +50,7 @@
@if(!string.IsNullOrEmpty(Url))
{
<input id="@(Name ?? GetId())" @ref="@fileUpload" @attributes="InputAttributes" type="file" multiple="@Multiple" accept="@Accept" disabled="@Disabled"
onchange="Radzen.uploadInputChange(event, '@Url', @Auto.ToString().ToLower(), @Multiple.ToString().ToLower(), true, '@ParameterName')" tabindex="-1" onkeydown="event.stopPropagation()"/>
onchange="Radzen.uploadInputChange(event, '@Url', @Auto.ToString().ToLower(), @Multiple.ToString().ToLower(), true, '@ParameterName', '@Method', @(Stream ? "true" : "false"))" tabindex="-1" onkeydown="event.stopPropagation()"/>
}
else
{

View File

@@ -101,6 +101,40 @@ namespace Radzen.Blazor
[Parameter]
public string? Url { get; set; }
/// <summary>
/// Specifies the HTTP method used for uploading files to the defined <see cref="Url"/> endpoint.
/// <para>
/// Common values are <c>POST</c> (default) and <c>PUT</c>.
/// </para>
/// <para>
/// If the <see cref="Url"/> parameter is not set, this property is ignored.
/// </para>
/// <para>
/// Defaults to <c>POST</c>.
/// </para>
/// </summary>
/// <value>The HTTP method for file upload requests.</value>
[Parameter]
public string Method { get; set; } = "POST";
/// <summary>
/// Enables streaming upload mode for large files to the specified <see cref="Url"/>.
/// <para>
/// When <c>true</c>, files are uploaded as raw binary streams instead of <c>multipart/form-data</c>.
/// Only a single file can be uploaded at a time in streaming mode.
/// </para>
/// <para>
/// When <c>false</c> (default), files are uploaded as <c>multipart/form-data</c> (standard form upload),
/// and multiple files can be uploaded simultaneously if <see cref="Multiple"/> is enabled.
/// </para>
/// <para>
/// This property is ignored if <see cref="Url"/> is not set.
/// </para>
/// </summary>
/// <value><c>true</c> to stream file data directly; otherwise, <c>false</c> (default).</value>
[Parameter]
public bool Stream { get; set; }
/// <summary>
/// Gets or sets the parameter name. If not set 'file' parameter name will be used for single file and 'files' for multiple files.
/// </summary>

View File

@@ -789,9 +789,9 @@ window.Radzen = {
return [table.nextSelectedIndex, table.nextSelectedCellIndex];
},
uploadInputChange: function (e, url, auto, multiple, clear, parameterName) {
uploadInputChange: function (e, url, auto, multiple, clear, parameterName, method = 'POST', stream = false) {
if (auto) {
Radzen.upload(e.target, url, multiple, clear, parameterName);
Radzen.upload(e.target, url, multiple, clear, parameterName, method, stream);
e.target.value = '';
} else {
Radzen.uploadChange(e.target);
@@ -865,20 +865,35 @@ window.Radzen = {
removeFileFromFileInput: function (fileInput) {
fileInput.value = '';
},
upload: function (fileInput, url, multiple, clear, parameterName) {
upload: function (fileInput, url, multiple, clear, parameterName, method = 'POST', stream = false) {
var uploadComponent = Radzen.uploadComponents && Radzen.uploadComponents[fileInput.id];
if (!uploadComponent) { return; }
if (!uploadComponent.files || clear) {
uploadComponent.files = Array.from(fileInput.files);
}
var data = new FormData();
var files = [];
var cancelled = false;
for (var i = 0; i < uploadComponent.files.length; i++) {
var file = uploadComponent.files[i];
data.append(parameterName || (multiple ? 'files' : 'file'), file, file.name);
files.push({Name: file.name, Size: file.size});
}
function asFormData() {
var data = new FormData();
var files = [];
for (var i = 0; i < uploadComponent.files.length; i++) {
var file = uploadComponent.files[i];
data.append(parameterName || (multiple ? 'files' : 'file'), file, file.name);
files.push({Name: file.name, Size: file.size});
}
return {data, files}
}
function asStream() {
if (uploadComponent.files.length > 0) {
var file = uploadComponent.files[0];
return {data: file, files: [{Name: file.name, Size: file.size}]};
}
return {data: null, files: []}
}
var cancelled = false;
var {data, files} = stream ? asStream() : asFormData();
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.upload.onprogress = function (e) {
@@ -925,7 +940,7 @@ window.Radzen = {
}
};
uploadComponent.invokeMethodAsync('GetHeaders').then(function (headers) {
xhr.open('POST', url, true);
xhr.open(method, url, true);
for (var name in headers) {
xhr.setRequestHeader(name, headers[name]);
}

View File

@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Hosting;
using System;
using System.IO;
using System.Threading.Tasks;
namespace RadzenBlazorDemos
{
@@ -16,6 +17,27 @@ namespace RadzenBlazorDemos
this.environment = environment;
}
[HttpPut("upload/stream")]
public async Task<IActionResult> Stream()
{
try
{
// Put your code here
using (var ms = new MemoryStream())
{
await Request.Body.CopyToAsync(ms);
byte[] fileBytes = ms.ToArray();
return Ok(new { Completed = true, fileSize = fileBytes.Length });
}
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
[HttpPost("upload/single")]
public IActionResult Single(IFormFile file)
{

View File

@@ -25,7 +25,9 @@
Upload files to a server
</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" class="rz-mb-8">
To upload files to a server set the <code>Url</code> property of the component. The URL should point to an action method in your server-side code that handles the file upload.
To upload files to a server, set the <code>Url</code> property of the component. The URL should point to an action method in your server-side code that handles the file upload.
By default, the upload uses the HTTP <code>POST</code> method and sends files as <code>multipart/form-data</code> (standard form upload). You can change this via the <code>Method</code> property to use a different HTTP method,
or enable <code>Stream</code> to upload the file's raw data. When <code>Stream</code> is set to <code>true</code>, only single-file upload is supported.
</RadzenText>
<RadzenExample ComponentName="Upload" Example="@nameof(UploadUrl)" AdditionalSourceCodePages=@(["/demos/Controllers/UploadController.cs"])>
<UploadUrl />

View File

@@ -1,5 +1,19 @@
<RadzenCard Variant="Variant.Outlined">
<RadzenUpload Url="upload/single" Style="width: 100%" Progress=@OnProgress
<RadzenUpload
ChooseText="Upload a single file as form data"
Url="upload/single"
Style="width: 100%"
Progress=@OnProgress
Complete=@OnComplete
InputAttributes="@(new Dictionary<string,object>{ { "aria-label", "select file" }})" />
<RadzenUpload
ChooseText="Upload a single file as stream"
Url="upload/stream"
Method="PUT"
Stream="true"
Multiple="false"
Style="width: 100%"
Progress=@OnProgress
Complete=@OnComplete
InputAttributes="@(new Dictionary<string,object>{ { "aria-label", "select file" }})" />
</RadzenCard>