尝试使用ASP.NET MVC 5中的MemoryStream发送电子邮件时,无法访问已关闭的Stream

时间:2016-05-27 21:43:21

标签: c# asp.net asp.net-mvc asp.net-mvc-5

我尝试通过在将数据保存到数据库后直接访问它来发送带附件的电子邮件。为此,我关注this tutorial

什么有效?

将附件存储在数据库中是正确的,因为当我转到详细信息页面时,我可以看到与配置文件关联的图像。

什么不是?

不幸的是,由于附件损坏,如何检索数据库中的文件似乎存在问题,例如:存储在数据库中的图像显示为153328 B,但是当发送时变为117B)。

实际成功并发送电子邮件(损坏的电子邮件)的解决方案取自this link,但当我尝试使用注释掉的流代码发送它时,代码在指示的行上崩溃:

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing); //this line
    }

这是我用来保存和检索附件的控制器代码:

 public async Task<ActionResult> Create([Bind(Include = "ID,LastName,FirstMidName")] Person person, HttpPostedFileBase upload)
    {
        if (ModelState.IsValid)
        {
            if (upload != null && upload.ContentLength > 0)
            {
                var avatar = new File
                {
                    FileName = System.IO.Path.GetFileName(upload.FileName),
                    FileType = FileType.Avatar,
                    ContentType = upload.ContentType
                };
                using (var reader = new System.IO.BinaryReader(upload.InputStream))
                {
                    avatar.Content = reader.ReadBytes(upload.ContentLength);
                }
                person.Files = new List<File> { avatar };
            }
            db.People.Add(person);
            db.SaveChanges();
            //await SendEmail(person.ID);
            var message = new MailMessage();
            var file = db.Files.Find(person.ID);
            Attachment attachment;
            var stream = new MemoryStream();
            try
            {
                stream.Write(file.Content, 0, file.Content.Length - 1);
                attachment = new Attachment(stream, file.FileName);
            }
            catch
            {
                stream.Dispose();
                throw;
            }
            //When i use this bit of code, I receive an error "Cannot access a closed stream
            //using (var stream = new MemoryStream())
            //{
            //    stream.Write(file.Content, 0, file.Content.Length - 1);
            //    attachment = new Attachment(stream, file.FileName);

            //}
            var fileSize = file.Content.Length;
            message.Attachments.Add(attachment);
            message.To.Add(new MailAddress("recipient@gmail.com"));  // replace with valid value
            message.From = new MailAddress("sender@outlook.com");  // replace with valid value
            message.Subject = "Your email subject";
            message.BodyEncoding =  System.Text.Encoding.UTF8;
            message.Body = "<p>file size: </p>" + "<p>" + fileSize + "</p>";
            message.IsBodyHtml = true;
            message.BodyEncoding = System.Text.Encoding.UTF8;

            using (var smtp = new SmtpClient())
            {
                //when i try to send the mail asynchronously the view with the form just keeps showing "waiting for localhost"
                //await smtp.SendMailAsync(message);
                smtp.Send(message);
                return RedirectToAction("Index");
            }

        }

        return View(person);
    }

其他问题 将附件发送到保存到数据库部分是不是一个好主意?

修改  我刚刚尝试使用以下代码行发送附件:

 message.Attachments.Add(new Attachment(upload.InputStream, Path.GetFileName(upload.FileName)));

之后添加:

 person.Files = new List<File> { avatar }; 

但仍然会收到损坏的附件..

编辑2:
     enter image description here
     enter image description here
     filesize

2 个答案:

答案 0 :(得分:3)

我想这一行

var file = db.Files.Find(person.ID)

实际应该是(你试图使用人物ID获取文件):

var file = db.Files.Find(avatar.ID)

但是,在您的情况下,您不需要从数据库中检索它。你已经有了那些字节,所以只需将它们包装在MemoryStream中,因为你不能直接发送upload.InputStream而不将其存储在内存中:

attachment = new Attachment(new MemoryStream(avatar.Content), file.FileName);

答案 1 :(得分:0)

快速看一下,我会看一下显而易见的事。

var file = db.Files.Find(person.ID);

看看这是什么回归。很可能在使用该对象之后,取决于它是什么对象,可能已经被处置掉了。

原因是你试图从file.Content.Length读取可能是问题的原因,因为它没有价值或其他什么。

逐行逐步完成逻辑。从最简单的方面分解,然后慢慢建立起来,直到你找到原因。另外,考虑从控制器中抽象逻辑并实现处理此操作的服务。检查存储库模式,工作单元和依赖注入作为旁注。

最终,你的问题,我认为这只是你没有检查所有“如果它不是你想要的那种”类型错误的事实,这就是为什么你最有可能也应该进行一些测试到位。 :P

解构,从基础开始,逐步建立起来。这样做,我相信你会发现问题所在。 :)