提问人:toiletboss 提问时间:8/11/2022 更新时间:8/12/2022 访问量:96
Asp.net/C# 在多个电子邮件下载时附加标头错误
Asp.net/C# append header error on mutliple email downloads
问:
我有一个 asp.net/c# 应用程序,它有一个功能,用户可以触发它是什么,然后下载一封电子邮件。如果有一封电子邮件被触发/下载,那完全可以正常工作。但是,如果有多封电子邮件,我会收到“发送 HTTP 标头后服务器无法追加标头”错误。我搞砸了,做了一些谷歌 fu,但似乎没有任何效果。
生成第一封电子邮件后,它会在“Response.AddHeaders”行上出错。
public void EmailDownload(string toAddress, string ccAddress, string subject, string body, string downloadName)
{
var assembly = typeof(SmtpClient).Assembly;
var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
using (MemoryStream stream = new MemoryStream())
{
MailMessage message = new MailMessage();
message.Body = body;
//message.To.Add(new MailAddress(toAddress));
message.To.Add(new MailAddress(emailAddress);
if (!string.IsNullOrEmpty(ccAddress))
{
message.CC.Add(new MailAddress(ccAddress));
}
//message.From = new MailAddress("[email protected]");
message.From = new MailAddress(emailAddress);
message.Subject = subject;
message.Headers.Add("X-Unsent", "1");
message.IsBodyHtml = true;
// Get reflection info for MailWriter contructor
var mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
// Construct MailWriter object with our FileStream
var mailWriter = mailWriterContructor.Invoke(new object[] { stream });
// Get reflection info for Send() method on MailMessage
var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
// Call method passing in MailWriter
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);
// Finally get reflection info for Close() method on our MailWriter
var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);
// Call close method
closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
byte[] data = stream.ToArray();
stream.Close();
Response.Clear();
Response.ContentType = "application/force-download";
Response.AddHeader("content-disposition", "attachment; filename=" + downloadName + ".eml");
Response.BinaryWrite(data);
//Response.End();
Response.Flush();
Response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
答:
0赞
Albert D. Kallal
8/12/2022
#1
您只能有一个页面响应来发送文件。执行此操作后,所有代码都将终止。
我不相信您可以一次发送/拥有多个页面的回复。您创建一个响应并发送它 - 您的代码现在在该时间点终止。
这建议,如果您希望用户获取/抓取/拥有多个文件,那么您需要一个 UI,如下所示:
标记是一个网格视图,我们有一个简单的 asp.net 按钮。所以这个:
标记:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" CssClass="table">
<Columns>
<asp:BoundField DataField="File Name" HeaderText="File" />
<asp:BoundField DataField="Date" HeaderText="Date" />
<asp:BoundField DataField="File Size" HeaderText="Size" />
<asp:TemplateField HeaderText="Select" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="cmdDownLoad" runat="server" Text="Download" cssclass="btn"
OnClick="cmdDownLoad_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
和按钮代码:
protected void cmdDownLoad_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gRow = btn.NamingContainer as GridViewRow;
string sFileOnly = gRow.Cells[0].Text;
string sFile = Server.MapPath("~/Content/Animals/" + sFileOnly);
string sMineType = MimeMapping.GetMimeMapping(sFile);
Response.ContentType = sMineType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + sFileOnly);
Response.TransmitFile(sFile);
Response.End();
}
事实上,如果我把代码放在响应结束之后,可以这样说:
Response.ContentType = sMineType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + sFileOnly);
Response.TransmitFile(sFile);
Response.End();
Debug.Print("code runs after above");
调试打印代码从不运行,因为我必须使用 response.end 来发送一个文件。一旦你这样做了 - 所有代码都会终止。
因此,您必须显示/提供电子邮件列表,并为用户提供一个按钮或一些按钮来下载每个文件。因此,您可以在代码中创建一个表,甚至创建一个 ListItem,并将其发送到网格。
并假设每次单击按钮都是一次回发,那么您必须将电子邮件列表保留在视图状态或会话中,以便在该网格中显示。您可以构建一个列表结构,将其传递给网格,因此 GV 将为您保留列表(请参阅我如何从上面的 GV 中获取文件)。
评论
0赞
toiletboss
8/12/2022
感谢您的深入回应!我将努力实现这一点,并让你知道!谢谢!
评论