【问题标题】:How to attach a PDF from a ConnectStream to an Email如何将 PDF 从 ConnectStream 附加到电子邮件
【发布时间】:2016-09-06 16:23:20
【问题描述】:

我正在调用一个在 ConnectStream 中返回 PDF 的 WebAPI。我将该 ConnectStream 写入文件,然后将其读回内存流,然后我可以将其附加到电子邮件中。我怎样才能在没有 IO 开销的情况下完成同样的事情?

System.Net.HttpWebResponse webResponse = (System.Net.HttpWebResponse)webRequest.GetResponse();

System.IO.Stream stream = webResponse.GetResponseStream();

System.IO.StreamReader reader = new System.IO.StreamReader(stream, Encoding.Default);

string finalPath = System.IO.Path.Combine(outputPath, $"{startDate:yyyy-MM-dd}_{endDate:yyyy-MM-dd}.pdf");
System.IO.Stream fileStream = System.IO.File.OpenWrite(finalPath);

using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fileStream, Encoding.Default))
{
    sw.Write(reader.ReadToEnd());
    sw.Flush();
    sw.Close();
}

using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(finalPath)))
{
    using (MailMessage mailMessage = new MailMessage())
    {
        mailMessage.From = new MailAddress("noreply@somedomain.com");

        mailMessage.To.Add("someone@somedomain.com");

        mailMessage.Attachments.Add(new Attachment(ms, new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Pdf)));
        SmtpClient smtpClient = new SmtpClient() { DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.SpecifiedPickupDirectory, PickupDirectoryLocation = outputPath };
        smtpClient.Send(mailMessage);
    }
}

【问题讨论】:

    标签: c# email pdf stream


    【解决方案1】:

    首先,请求流是单向只读流,不能传递给大多数允许流的方法,因此您需要将其读入您可以操作的东西:

        public byte[] ReadStreamBinary(Stream stream, int bufferSize)
        {
            using (var ms = new MemoryStream())
            {
                var buffer = CreateBuffer(bufferSize);
                var finished = false;
                while (!finished)
                {
                    buffer.Initialize();
                    var bytes = stream.Read(buffer, 0, buffer.Length);
                    if (bytes > 0)
                    {
                        ms.Write(buffer, 0, bytes);
                    }
                    else
                    {
                        finished = true;
                    }
                }
                return ms.ToArray();
            }
        }
    

    然后你可以从这个字节数组创建你的 MemoryStream。

    由于流的默认内部缓冲区为 4k,因此我几乎总是将其用作缓冲区大小 (4096)。在您的情况下,仅修改方法以直接返回 MemoryStream 可能更容易。

    如果您决定返回流,则需要删除 using(因此流不会被关闭/处置)并将流指针返回到开头。

        public MemoryStream ReadStreamBinary(Stream stream, int bufferSize)
        {
            var ms = new MemoryStream();
            var buffer = CreateBuffer(bufferSize);
            var finished = false;
            while (!finished)
            {
                buffer.Initialize();
                var bytes = stream.Read(buffer, 0, buffer.Length);
                if (bytes > 0)
                {
                    ms.Write(buffer, 0, bytes);
                }
                else
                {
                    finished = true;
                }
            }
    
            ms.Seek(0, SeekOrigin.Begin);
            return ms;
        }
    

    只记得在调用方法中关闭/释放流。

    哎呀。差点忘了包含 CreateBuffer 代码,把它放在你的类中的任何地方:

    public static Func<int, byte[]> CreateBuffer = x => (byte[])Array.CreateInstance(typeof(byte), x);
    

    【讨论】:

    • 谢谢!为什么不能使用 CopyTo 方法将 Stream 复制到 MemoryStream 中?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 2020-11-21
    • 2016-01-18
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    相关资源
    最近更新 更多