Недопустимая длина для массива символов или строки Base-64 в больших двоичных объектах PDF из Dynamics CRM

#c# #crm #microsoft-dynamics

#c# #crm #microsoft-dynamics

Вопрос:

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

Этот процесс, похоже, отлично работает с файлами изображений, такими как .PNG и т. Д., Excel .xls и т. Д., Но когда я пытаюсь преобразовать файл PDF в массив байтов на C #, я получаю сообщение об ошибке:

Недопустимая длина для массива символов Base-64 или строки в строке Convert.FromBase64String().

 var binaryData = File.ReadAllText(@"E:teststream.txt");
byte[] byteArray = Convert.FromBase64String(binaryData);
File.WriteAllBytes(@"E:testfile.pdf", byteArray);
  

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

Я нашел другую ссылку на ту же проблему, https://social.microsoft.com/Forums/en-US/7a28e106-3715-42b9-a743-9e5207a02540/problem-while-decoding-the-body-field-of-activitymimeattachment-entity?форум =crm

Но решение состояло в том, чтобы просто перебирать байтовый массив и записывать каждый байт по отдельности, он все равно попадает в поврежденный файл PDF, который не открывается в Acrobat.

В конечном счете, я буду считывать двоичные данные из поля базы данных или через CRM API, но я просто хотел сначала проверить теорию, и, похоже, я хорошо разбираюсь во всех типах вложений, кроме PDF…

Комментарии:

1. В одном сообщении, которое я видел, говорилось, что попробуйте заполнить двоичные данные перед преобразованием в байтовый массив .. я попробовал что-то вроде приведенного ниже, и я прошел мимо ошибки преобразования, но PDF-файл по-прежнему поврежден: string DummyData = b.Trim().Replace(» «, » «); if (DummyData. Длина % 4 > 0) DummyData = DummyData.PadRight(DummyData. Длина 4 — DummyData. Длина % 4, ‘=’); byte[] ByteArray = Convert.FromBase64String(DummyData);

2. Работа с байтами и работа с текстом — это совершенно разные задачи в программировании. При преобразовании текста в байты (и наоборот) программа будет форматировать байты на основе предположений о кодировке, порядке байтов и локализации, чтобы назвать несколько примеров. Если это не является абсолютно необходимым для преобразования файла в текст, вы должны обрабатывать файл как массив байтов от начала до конца.

Ответ №1:

Это всего лишь мое предположение, я понятия не имею, работает ли это.

Иногда кодировка символов неверна, потому что текстовые файлы могут иметь спецификацию (метку порядка байтов), и только произвольные двоичные данные могут ей мешать. Вы можете принудительно преобразовать кодировку в ASCII, прочитав данные в двоичном byte[] формате, а затем преобразовав их в ASCII, как показано здесь:

 byte[] data;

data = File.ReadAllBytes(@"E:teststream.txt");
string base64 = System.Text.Encoding.ASCII.GetString(data);
data = Convert.FromBase64String(base64);
File.WriteAllBytes(@"E:testfile.pdf", data);
  

Давайте посмотрим, решит ли это что-нибудь.

Комментарии:

1. спасибо, я попробовал использовать кодировку ASCII.. в итоге мой исходный поток был плохим для файлов размером более 32 КБ .. поскольку он работал с небольшими файлами, я ошибочно предположил, что моя методология была правильной.. но это было не так.. спасибо за ответ.

Ответ №2:

я узнал, что значение в поле BODY в таблице SQL содержит только 32 КБ потока больших двоичных объектов. я понятия не имею, где находится его сброс. я поспрашивал, и все сказали, что «получение из SQL не поддерживается».. хотя чтение данных из отфильтрованных представлений CRM SQL поддерживается…

итак, когда я тестировал с небольшими файлами PNG и JPG, все было в порядке, но если бы я попробовал файл большего размера, это не сработало бы, я нажал, когда все самые большие потоки были 32 КБ при сохранении в файловой системе.

в конце концов я решил эту проблему, получив данные потока вложений через CRM SDK, а не из SQL в представлении FilteredEmailAttachment в SQL

    var attachments = (from a in cc.CRMContext.ActivityMimeAttachments where a.ActivityId == email.ActivityId select a).ToList();
                foreach (var attachment in attachments)
                {
                    byte[] byteArray = Convert.FromBase64String(attachment.Body);
                    System.IO.File.WriteAllBytes(@"E:testtemp"   attachment.FileName, byteArray);
                }
  

Ответ №3:

Поскольку это ошибка, возникающая из-за логики проверки, возможно, вы могли бы проверить, есть ли пробелы в данных base64, и если они есть, замените их на ‘ ‘. Копирование сценария проблемы с решением, о котором я говорю.

 var binaryData = File.ReadAllText(@"E:teststream.txt");
byte[] byteArray = Convert.FromBase64String(binaryData.Replace(' ', ' '));
File.WriteAllBytes(@"E:testfile.pdf", byteArray);
  

В прошлом у меня это работало.