Преобразование строки Base64 во вложение изображения

У меня есть изображение, преобразованное в строку base64, которую мне нужно преобразовать обратно в изображение и прикрепить к MailMessage.

Вот соответствующий код, преобразующий его из строки base64 в изображение (я думаю, что могу пропустить объект Image и сделать это, используя один поток памяти, но у меня были некоторые проблемы с реализацией этого). Попытка сохранить Image в MemoryStream приводит к общей ошибке GDI+:

Image image = ImageHelper.Base64ToImage(attachment.FieldData);

if (image != null)
{
    using (var ms = new MemoryStream())
    {
        image.Save(ms, ImageFormat.Png); // Throws a generic GDI+ error on Save

        ms.Position = 0;

        var imageAttachment = new Attachment(ms, "image.png", "image/png");

        message.Attachments.Add(imageAttachment);
    }
}

public static class ImageHelper
{
    public static Image Base64ToImage(string base64String)
    {
        if (string.IsNullOrEmpty(base64String))
        {
            return null;
        }

        byte[] imageBytes = Convert.FromBase64String(base64String);

        using (var ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
        {
            ms.Write(imageBytes, 0, imageBytes.Length);

            Image image = Image.FromStream(ms, true);

            return image;
        }
    }
}

Я могу обслуживать необработанную строку base64 в другом месте, используя тег img, и он работает нормально, поэтому я уверен, что проблема не в самой строке base64:

<img src="data:image/png;base64,<myBase64StringHere>" alt="My Image" width="500" />

Я, должно быть, делаю что-то неправильно при преобразовании его обратно, но я не смог понять проблему. Спасибо за любую помощь в этом!


person Elliot Starks    schedule 24.10.2016    source источник
comment
Вы уверены, что изображение имеет color management information embedded in the data stream? Возможно, вы хотели только проверить образ, и в этом случае используйте эта перегрузка с false для встроенных цветов: Image.FromStream(ms, false, true);.   -  person Quantic    schedule 25.10.2016
comment
Я пробовал как Image.FromStream(ms, false, true), так и Image.FromStream(ms), но все равно получаю ту же ошибку A generic error occurred in GDI+. на Image.Save(ms, ImageFormat.Png)   -  person Elliot Starks    schedule 25.10.2016
comment
Думаю, я нашел вашу проблему, прочитав здесь, вы не используете Bitmap, но то же самое происходит с Image.FromStream(): поток должен оставаться открытым в течение всего времени жизни изображения. Однако вы являетесь using MemoryStream, поэтому он удаляется по мере возврата изображения, и как только это происходит, Image больше нельзя использовать. Возможно, ваш статический класс должен возвращать Tuple<Image, MemoryStream>.   -  person Quantic    schedule 25.10.2016
comment
Это действительно была проблема, большое спасибо! Если вы опубликуете это как ответ, я могу принять это.   -  person Elliot Starks    schedule 25.10.2016


Ответы (1)


Image.FromStream(Stream) говорит: "Вы должны сохранить stream open for the life of Image", но ваш оператор using удаляет поток по мере возврата Image. Обходным решением было бы вернуть изображение и поток вместе в виде кортежа и без using:

public static Tuple<Image, MemoryStream> Base64ToImage(string base64String)
{
    if (string.IsNullOrEmpty(base64String))
    {
        return null;
    }

    byte[] imageBytes = Convert.FromBase64String(base64String);
    var ms = new MemoryStream(imageBytes, 0, imageBytes.Length)        
    ms.Write(imageBytes, 0, imageBytes.Length);
    Image image = Image.FromStream(ms, true);

    return new Tuple<Image, MemoryStream>(image, ms);
}

Также обратите внимание на то, чтобы позаботиться и просмотреть каждую перегрузку на страницах MSDN. Обычно я бы сказал: «Просмотрите наиболее полную перегрузку, чтобы получить все примечания и примечания», но в данном случае это неверно. Страница MSDN для самой большой перегрузки, Image.FromStream Method (Stream, Boolean, Boolean) не упоминает, что вам нужно держать поток открытым, но я совершенно уверен, что это ошибка на этой конкретной странице.

person Quantic    schedule 25.10.2016