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

Angular中调用SignalR的invoke方法传文件时服务端接口未触发如何解决

问题根因

SignalR 默认使用 JSON 序列化器传输数据,不支持直接序列化 FormData 对象,也无法在服务端自动绑定到 IFormFile 类型,这是你调用服务端方法无响应的核心原因。IFormFile 是 ASP.NET Core 用于绑定 HTTP 表单请求的类型,不适用于 SignalR 的调用场景。

解决方案

第一步:修改前端传参逻辑

不要用 FormData 封装参数,将文件转为 Base64 字符串后,和其他参数一起传递:

async fileUpload(username: string, file: File) {
  // 把File对象转成Base64字符串
  const fileBase64 = await this.convertFileToBase64(file);
  return this.hubConnection.invoke('FileUpload', {
    recipientUsername: username,
    fileName: file.name,
    contentType: file.type,
    fileBase64: fileBase64
  }).catch(error => console.log(error));
}

// 辅助方法:File转Base64
private convertFileToBase64(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      // 去掉base64的头部标识 比如data:image/png;base64,
      const base64 = (reader.result as string).split(',')[1];
      resolve(base64);
    };
    reader.onerror = error => reject(error);
  });
}

第二步:修改服务端 FileDto 定义

替换 IFormFile 为对应的参数字段:

public class FileDto
{
    public string RecipientUsername { get; set; }
    public string FileName { get; set; }
    public string ContentType { get; set; }
    public string FileBase64 { get; set; }
}

第三步:修改服务端文件存储逻辑

把 Base64 字符串转为字节数组后写入文件:

public async Task FileUpload(FileDto createFileDto)
{
    var username = Context.User.GetUsername();

    if(username == createFileDto.RecipientUsername.ToLower())
        throw new HubException("You cannot send file to youself");
    
    var sender = await _userRepository.GetUserByUsernameAsync(username);
    var recipient = await _userRepository.GetUserByUsernameAsync(createFileDto.RecipientUsername);

    if(recipient == null) throw new HubException("Not Found User");
    
    var message = new Message();
    string groupName ="";
    if(!string.IsNullOrEmpty(createFileDto.FileBase64))
    {
        if(!Directory.Exists(AppDirectory))
            Directory.CreateDirectory(AppDirectory);
        
        var fileBytes = Convert.FromBase64String(createFileDto.FileBase64);
        var fileFormat = Path.GetExtension(createFileDto.FileName);
        var fileName = DateTime.Now.Ticks.ToString() + fileFormat;
        var path = Path.Combine(AppDirectory, fileName);

        await File.WriteAllBytesAsync(path, fileBytes);

        message = new Message
        {
            Sender = sender,
            Recipient = recipient,
            SenderUsername = sender.UserName,
            RecipientUsername = recipient.UserName,
            IsFile = true,
            Content = "",
            FileName = createFileDto.FileName,
            FileFormat = fileFormat,
            ContentType = createFileDto.ContentType,
            FilePath = path
        };

        groupName = GetGroupName(sender.UserName, recipient.UserName);

        var group = await _messageRepository.GetMessageGroup(groupName);

        if (group.Connections.Any(x => x.Username == recipient.UserName))
        {
            message.DateRead = DateTime.UtcNow;
        }
        else
        {
            var connections = await _tracker.GetConnectionsForUser(recipient.UserName);
            if (connections != null)
            {
                await _presenceHub.Clients.Clients(connections).SendAsync("NewMessageReceived",
                    new { username = sender.UserName, knownAs = sender.KnownAs });
            }
        }
        _messageRepository.AddMessage(message);
    }

    if(await _messageRepository.SaveAllAsync() && groupName != "")
    {
        await Clients.Group(groupName).SendAsync("NewMessage",_mapper.Map<MessageDto>(message));
    }
}

可选检查项

如果修改后还是无法触发方法,检查以下配置:

  • 确认前端 SignalR 连接已经成功建立,没有权限验证失败等报错
  • 如果服务端配置了 JsonSerializerOptions.PropertyNameCaseInsensitive = false,保证前后端参数名大小写完全匹配,或者给服务端方法加 [HubMethodName("FileUpload")] 特性显式指定方法名
  • 如果文件过大,调整 SignalR 的最大消息大小配置:
builder.Services.AddSignalR(options =>
{
    options.MaximumReceiveMessageSize = 10 * 1024 * 1024; // 调整为你需要的大小,比如10M
});

内容的提问来源于stack exchange,提问作者Shanto Siddiq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 23:57:03