如何将ConnectStream中的PDF附加到电子邮件

时间:2016-09-06 16:23:20

标签: c# email pdf stream

我正在调用一个在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);
    }
}

1 个答案:

答案 0 :(得分: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。

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

    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);