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

如何将Controller生成的MimePart变量传递到Blazor页面代码隐藏类?

问题根源

你当前的实现思路存在架构逻辑错误:MimePart是MimeKit生成的进程内内存对象,生命周期仅存在于Controller单次请求的处理过程中,请求结束后相关内存资源就会被释放,不存在可以直接跨请求传递到Blazor端的对象引用,强行用静态变量、临时缓存存这类对象还会引发并发冲突、内存泄漏、多用户数据串流的问题,完全不具备可行性。

你不需要实现「Controller生成MimePart再传回Blazor」的逻辑,根据你用的Blazor托管模式选下面两种方案即可:


方案1:直接在Blazor侧生成MimePart(适合Blazor Server模式,实现最简单)

Blazor本身就能直接拿到用户选中的上传文件,完全不需要绕一层Controller生成MimePart,直接在SendMail方法里读取文件生成附件即可:

  1. 先在页面代码隐藏类里加变量存用户选中的文件,绑定文件选择组件的变更事件:
// 限制最大上传文件数,按需调整
private const int MaxFileCount = 10;
// 单文件大小上限,这里设为10MB,按需调整
private const long MaxFileSize = 10 * 1024 * 1024;
private IReadOnlyList<IBrowserFile> _selectedFiles = Array.Empty<IBrowserFile>();

private void OnFileSelected(InputFileChangeEventArgs e)
{
    _selectedFiles = e.GetMultipleFiles(MaxFileCount);
}
  1. 改造原有的SendMail方法,直接遍历选中的文件生成MimePart加入邮件体:
private async Task SendMail()
{
    try
    { 
        var email = new MimeMessage();
        email.From.Add(MailboxAddress.Parse(sender));
        email.To.Add(MailboxAddress.Parse(receiver));
        email.Subject = emailSubject;
        var multipart = new Multipart("mixed");
        multipart.Add(new TextPart(TextFormat.Html) { Text = emailMessage });

        // 直接遍历选中文件生成附件,无需走Controller
        foreach (var file in _selectedFiles)
        {
            var memoryStream = new MemoryStream();
            await using var uploadStream = file.OpenReadStream(MaxFileSize);
            await uploadStream.CopyToAsync(memoryStream);
            memoryStream.Position = 0;

            var contentType = ContentType.Parse(file.ContentType);
            var attachmentPart = new MimePart(contentType.MimeType)
            {
                FileName = file.Name,
                ContentTransferEncoding = ContentEncoding.Base64,
                Content = new MimeContent(memoryStream),
            };
            multipart.Add(attachmentPart);
        }

        email.Body = multipart;
        using var smtp = new SmtpClient();
        smtp.Connect(outgoingServer, outgoingPort, SecureSocketOptions.Auto);
        smtp.Authenticate(userName, userPassword);
        smtp.Send(email);
        smtp.Disconnect(true);
    }
    catch (Exception ex)
    {
        NotificationService.Notify(NotificationSeverity.Error, "Send Email Error!", ex.Message, 7000);
    }
}

注意:Blazor WebAssembly模式不要用这个方案,SMTP的账号、密码、服务器地址会打包到前端程序集泄露给所有用户,这种场景用方案2。


方案2:合并上传与发信逻辑到Controller(适合Blazor WebAssembly模式,安全性更高)

如果是WASM模式,所有SMTP相关逻辑必须放在服务端,不要拆分「上传文件」和「发送邮件」两个独立接口,直接写一个统一接口接收文件和邮件参数,在Controller内部完成MimePart生成、邮件组装、发送全流程,根本不需要把MimePart传回Blazor:

  1. 先定义接口接收的参数模型:
public class SendMailRequest
{
    public string Sender { get; set; }
    public string Receiver { get; set; }
    public string Subject { get; set; }
    public string HtmlContent { get; set; }
}
  1. 改造Controller,合并原有上传和发信逻辑:
[HttpPost("mail/send-with-attachments")]
public async Task<IActionResult> SendWithAttachments([FromForm] SendMailRequest request, [FromForm] IFormFile[] files)
{
    try
    {
        var email = new MimeMessage();
        email.From.Add(MailboxAddress.Parse(request.Sender));
        email.To.Add(MailboxAddress.Parse(request.Receiver));
        email.Subject = request.Subject;
        var multipart = new Multipart("mixed");
        multipart.Add(new TextPart(TextFormat.Html) { Text = request.HtmlContent });

        foreach (var file in files)
        {
            var contentStream = new MemoryStream();
            await file.CopyToAsync(contentStream);
            contentStream.Position = 0;

            var contentType = ContentType.Parse(file.ContentType);
            var part = new MimePart(contentType.MimeType)
            {
                FileName = Path.GetFileName(file.FileName),
                ContentTransferEncoding = ContentEncoding.Base64,
                Content = new MimeContent(contentStream),
            };
            multipart.Add(part);
        }
        email.Body = multipart;

        // SMTP配置建议从配置文件读取,不要硬编码
        using var smtp = new SmtpClient();
        smtp.Connect(outgoingServer, outgoingPort, SecureSocketOptions.Auto);
        smtp.Authenticate(userName, userPassword);
        smtp.Send(email);
        smtp.Disconnect(true);

        return Ok();
    }
    catch (Exception ex)
    {
        return StatusCode(500, ex.Message);
    }
}
  1. Blazor端只需要用MultipartFormDataContent把邮件参数和选中的文件一起提交到这个接口即可,不需要处理任何MimePart和SMTP逻辑。

内容的提问来源于stack exchange,提问作者David Gammon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 12:48:19