Только часть потока записывается в компонент конвейера

Я создаю компонент конвейера, который может преобразовать формат изображения в другой формат (например, с jpg в png):

using (System.Drawing.Bitmap bmpSource = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(msgReceived.BodyPart.Data))
{
    VirtualStream strConvertedImage = new VirtualStream();

    bmpSource.Save(strConvertedImage, System.Drawing.Imaging.ImageFormat.Png);

    strConvertedImage.Flush();
    strConvertedImage.Position = 0;

    ctxPipeline.ResourceTracker.AddResource(strConvertedImage);
}

msgReceived.BodyPart.Data = strConvertedImage;

Я использую этот компонент в приемном конвейере с файловым адаптером, и он работает нормально, но когда я подписываюсь на сквозной порт отправки и файловый адаптер, записанный файл является лишь частью реального изображения.

Замечания:

Я могу использовать этот же код (за исключением загрузки исходного растрового изображения из потока файлов вместо потока сообщений BizTalk) в консольном приложении Windows, и он работает нормально, так что это похоже на BizTalk.

Я думаю, что это как-то связано с исходным потоком.

Это кажется странным поведением, но если я проверяю свойства длины и позиции msgReceived.BodyPart.Data, длина равна 904678. Позиция равна 0. Позиция остается равной 0 и никогда не меняется, даже когда битовая карта загружается и сохраняется. Я ожидал бы, что при загрузке растрового изображения положение изменится, если только метод BitMap.FromStream не начнет поиск потока после завершения загрузки.

Кроме того, когда я сохраняю растровое изображение в своем новом потоке в виде png, длина нового потока всегда равна 54789, представляя только первую сторону изображения. Теперь, если я немедленно сохраню тот же объект растрового изображения в новом потоке, его размер будет 1400868, представляющий все изображение, а msgReceived.BodyPart.Data.Position теперь равен 904678, что означает, что весь исходный поток был прочитан.

Вот пример:

using (System.Drawing.Bitmap bmpSource = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(msgReceived.BodyPart.Data))
{
    VirtualStream strConvertedImage = new VirtualStream();
    bmpSource.Save(strConvertedImage, System.Drawing.Imaging.ImageFormat.Png);
    strConvertedImage.Flush();
    strConvertedImage.Position = 0;

    //msgReceived.BodyPart.Data.Position is 0
    //msgReceived.BodyPart.Data.Length is 904678
    //strConvertedImage.Position is 54789 (Only part of image was saved)

    strConvertedImage = new VirtualStream();
    bmpSource.Save(strConvertedImage, System.Drawing.Imaging.ImageFormat.Png);

    //msgReceived.BodyPart.Data.Position is 904678
    //msgReceived.BodyPart.Data.Length is 904678
    //strConvertedImage.Position is 1400868 (full image was saved)

    msgReceived.BodyPart.Data = strConvertedImage;
    ctxPipeline.ResourceTracker.AddResource(strConvertedImage);
}

Почему позиция msgReceived.BodyPart.Data продвигается только во втором сохранении? И почему бы при первой попытке сохранения сохранить только часть преобразованного изображения. Я сбит с толку!

1 ответ

Я бы не использовал Data свойство кроме того, чтобы установить поток в конце; на MSDN он клонирует поток данных и иногда дает неожиданное поведение (я видел Data свойство быть нулевым в некоторых адаптерах, даже если GetOriginalDataStream() успешно вернул поток). использование GetOriginalDataStream() вместо. Я бы также избегал использования using блоки в конвейере - хотя я не могу понять, почему ваш пример будет проблемой, очень легко ошибочно избавиться от потока, который в итоге удаляет исходный поток данных.

Например,

Stream originalStream = msgReceived.BodyPart.GetOriginalDataStream();
originalStream.Seek(0, SeekOrigin.Begin);
VirtualStream vtsConvertedImage = new VirtualStream()
System.Drawing.Bitmap bmpSource = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(originalStream);

bmpSource.Save(vtsConvertedImage, System.Drawing.Imaging.ImageFormat.Png);

vtsConvertedImage.Flush();
vts.ConvertedImage.Seek(0, SeekOrigin.Begin);

msgReceived.BodyPart.Data = vtsConvertedImage;
ctxPipeline.ResourceTracker.AddResource(vtsConvertedImage);
ctxPipeline.ResourceTracker.AddResource(bmpSource);
Другие вопросы по тегам