You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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; }
}

问题根源

  1. 未传递文件实际内容:客户端仅序列化了FileInfo对象,但该对象的RawFile为object类型,无法序列化文件二进制内容,后端未收到任何文件数据。
  2. 后端流处理错误:后端创建的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:05:13