使用Syncfusion Blazor Uploader上传至Azure Blob后文件大小为0字节问题
问题:Syncfusion Blazor Uploader上传Azure Blob后文件大小为0字节
使用Syncfusion Blazor Uploader组件,客户端通过服务转发请求到后端控制器,将文件上传至Azure Blob Storage。文件能成功上传至Blob但无报错,不过上传后的文件大小始终为0字节,已尝试调整ContentType及更换文件类型,结果一致。
客户端OnChange事件代码
private async Task OnChange(UploadChangeEventArgs args) { foreach (var file in args.Files) { try { var serializedFile = JsonSerializer.Serialize<Syncfusion.Blazor.Inputs.FileInfo>(file.FileInfo); await RemoteService.UploadStudyGuide(serializedFile); } catch (Exception ex) { Console.WriteLine(ex.Message); } } }
服务层转发代码
public async Task UploadStudyGuide(string serializedFile) { var response = await _httpClient.PostAsJsonAsync("StudyGuide/Upload", serializedFile); }
后端控制器代码
[HttpPost("Upload")] public async Task Upload([FromBody] string serializedFile) { string devConnectionString = "myConnectionString"; string blobContainerName = "myContainerName"; var file = JsonSerializer.Deserialize<Syncfusion.Blazor.Inputs.FileInfo>(serializedFile); try { var container = new BlobContainerClient(devConnectionString, blobContainerName); var createResponse = await container.CreateIfNotExistsAsync(); if (createResponse != null && createResponse.GetRawResponse().Status == 201) await container.SetAccessPolicyAsync(Azure.Storage.Blobs.Models.PublicAccessType.Blob); var blob = container.GetBlobClient($"/ASPTDEV/StudyGuides/{file.Name}"); await blob.DeleteIfExistsAsync(Azure.Storage.Blobs.Models.DeleteSnapshotsOption.IncludeSnapshots); using (var fileStream = new FileStream(blob.BlobContainerName, FileMode.Create)) { await blob.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = $"{file.MimeContentType}" }); fileStream.Close(); } } catch (Exception e) { Response.Clear(); Response.StatusCode = 204; Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "File failed to upload"; Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = e.Message; } }
Syncfusion FileInfo类定义
public class FileInfo { [JsonPropertyName("fileSource")] public string FileSource { get; set; } [JsonPropertyName("id")] public string Id { get; set; } [JsonPropertyName("input")] public DOM Input { get; set; } [JsonPropertyName("list")] public DOM List { get; set; } [JsonPropertyName("name")] public string Name { get; set; } [DefaultValue(null)] [JsonPropertyName("rawFile")] public object RawFile { get; set; } [JsonPropertyName("size")] public double Size { get; set; } [JsonPropertyName("status")] public string Status { get; set; } [JsonPropertyName("statusCode")] public string StatusCode { get; set; } [JsonPropertyName("type")] public string Type { get; set; } [JsonPropertyName("mimeContentType")] public string MimeContentType { get; set; } [JsonPropertyName("lastModifiedDate")] public DateTime LastModifiedDate { get; set; } [JsonPropertyName("validationMessages")] public ValidationMessages ValidationMessages { get; set; } }
问题根源
- 未传递文件实际内容:客户端仅序列化了FileInfo对象,但该对象的
RawFile为object类型,无法序列化文件二进制内容,后端未收到任何文件数据。 - 后端流处理错误:后端创建的
FileStream参数为容器名称,相当于生成了一个空流,上传后Blob自然为0字节。
修复方案
1. 客户端修改:传递文件二进制数据
private async Task OnChange(UploadChangeEventArgs args) { foreach (var file in args.Files) { try { // 读取文件二进制内容 using var stream = file.File.OpenReadStream(); var bytes = new byte[stream.Length]; await stream.ReadAsync(bytes, 0, (int)stream.Length); // 封装文件信息与二进制数据 var uploadModel = new { FileInfo = file.FileInfo, FileBytes = bytes }; var serializedData = JsonSerializer.Serialize(uploadModel); await RemoteService.UploadStudyGuide(serializedData); } catch (Exception ex) { Console.WriteLine(ex.Message); } } }
2. 后端新增接收模型
public class FileUploadModel { public Syncfusion.Blazor.Inputs.FileInfo FileInfo { get; set; } public byte[] FileBytes { get; set; } }
3. 后端控制器修改:使用内存流上传实际内容
[HttpPost("Upload")] public async Task Upload([FromBody] FileUploadModel uploadModel) { string devConnectionString = "myConnectionString"; string blobContainerName = "myContainerName"; var fileInfo = uploadModel.FileInfo; var fileBytes = uploadModel.FileBytes; try { var container = new BlobContainerClient(devConnectionString, blobContainerName); await container.CreateIfNotExistsAsync(); // 移除路径开头斜杠,避免Blob路径异常 var blob = container.GetBlobClient($"ASPTDEV/StudyGuides/{fileInfo.Name}"); await blob.DeleteIfExistsAsync(Azure.Storage.Blobs.Models.DeleteSnapshotsOption.IncludeSnapshots); // 使用内存流上传实际文件内容 using var memoryStream = new MemoryStream(fileBytes); await blob.UploadAsync(memoryStream, new BlobHttpHeaders { ContentType = fileInfo.MimeContentType }); } catch (Exception e) { Response.Clear(); // 改用500状态码表示服务器错误,204易误导 Response.StatusCode = 500; Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = $"File failed to upload: {e.Message}"; } }
额外优化
- 避免使用
FileStream创建本地文件,改用MemoryStream处理二进制数据,减少不必要的IO操作。 - 异常返回状态码调整为500,符合上传失败的场景语义。
内容的提问来源于stack exchange,提问作者Frawsty
相关产品推荐
相关产品推荐

