正确处理字节数组编码Utf-8

问题描述

我试图下载PDF文件并以UTF-8格式对其进行编码,然后将其转换回Base64以将其附加到MailMessage,但是将字符串传递给Base64时出现异常。

例外 输入不是有效的Base-64字符串,因为它包含非base 64字符...

我的代码...

  try
            {
                if (attachment.Uri.Contains("http") || attachment.Uri.Contains("https"))
                {
                    byte[] contentByte = null;
                    using (var webClient = new WebClient())
                    {
                        webClient.UseDefaultCredentials = true;
                        Uri uri = new Uri(attachment.Uri);
                        contentByte = webClient.DownloadData(uri);
                    }


                    MemoryStream memStream = new MemoryStream(contentByte);

                    String fullString = Encoding.UTF8.GetString(memStream.ToArray());
                    String stringData = fullString.Split(',')[1];
                    byte[] byteData = System.Convert.FromBase64String(stringData);
                    
                    MemoryStream streamData = new MemoryStream(byteData);
                    Attachment attachmentDoc = new Attachment(streamData,fileName);

                    mail.Attachments.Add(attachmentDoc);
                }
            }
            catch (Exception ex)
            {
                notificationLog.Error.Write(String.Format("Sendmail error. Attachment not found: " + attachment.FileName));
            }

解决方法

您将以错误的方式进行操作。

您正尝试将PDF作为UTF-8解码(不是)为UTF-16,然后尝试将该UTF-16解码为Base64(将其解码)。 (不是)字节数组,然后将这些字节附加到电子邮件中。这与您的需求完全相反。

Base64以字节为单位,而不是字符串/字符。在Base64中编码之前,无需将PDF(二进制文件)编码到UTF-8。只需编码 PDF字节原样直接到达Base64,例如:

try
{
    if (attachment.Uri.StartsWith("http:") || attachment.Uri.StartsWith("https:"))
    {
        byte[] contentByte = null;
        using (var webClient = new WebClient())
        {
            webClient.UseDefaultCredentials = true;
            Uri uri = new Uri(attachment.Uri);
            contentByte = webClient.DownloadData(uri);
        }

        String stringData = System.Convert.ToBase64String(contentByte);
        MemoryStream memStream = new MemoryStream(Encoding.ASCII.GetBytes(stringData));

        Attachment attachmentDoc = new Attachment(memStream,fileName);
        mail.Attachments.Add(attachmentDoc);
    }
}
catch (Exception ex)
{
    notificationLog.Error.Write(String.Format("Sendmail error. Attachment not found: " + attachment.FileName));
}

但是,使用这种方法,接收器将无法正确解码PDF,因为它不知道PDF字节是在Base64中编码的。

幸运的是,Attachment类可以为您处理Base64,并将编码通知接收者。只需按原样提供Attachment原始PDF字节,并将其TransferEncoding属性设置为Base64,例如:

try
{
    if (attachment.Uri.StartsWith("http:") || attachment.Uri.StartsWith("https:"))
    {
        byte[] contentByte = null;
        using (var webClient = new WebClient())
        {
            webClient.UseDefaultCredentials = true;
            Uri uri = new Uri(attachment.Uri);
            contentByte = webClient.DownloadData(uri);
        }

        MemoryStream memStream = new MemoryStream(contentByte);

        Attachment attachmentDoc = new Attachment(memStream,fileName);
        attachmentDoc.TransferEncoding = TransferEncoding.Base64;

        mail.Attachments.Add(attachmentDoc);
    }
}
catch (Exception ex)
{
    notificationLog.Error.Write(String.Format("Sendmail error. Attachment not found: " + attachment.FileName));
}