Ввод не является допустимой строкой Base-64, так как он содержит символ, отличный от base 64.


98

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

Исключение, полученное при преобразовании потока обратно в байтовый, -

Ввод не является допустимой строкой Base-64, так как он содержит символ, отличный от base 64, более двух символов заполнения или символ, не являющийся пробелом, среди символов заполнения

В службе:

[WebGet(UriTemplate = "ReadFile/Convert", ResponseFormat = WebMessageFormat.Json)]  
public string ExportToExcel()
  {
      string filetoexport = "D:\\SomeFile.xls";
      byte[] data = File.ReadAllBytes(filetoexport);
      var s = Convert.ToBase64String(data);
      return s;
  }

В приложении:

       var client = new RestClient("http://localhost:56877/User/");
       var request = new RestRequest("ReadFile/Convert", RestSharp.Method.GET);
       request.AddHeader("Accept", "application/Json");
       request.AddHeader("Content-Type", "application/Json");
       request.OnBeforeDeserialization = resp => {resp.ContentType =    "application/Json";};
       var result = client.Execute(request);
       byte[] d = Convert.FromBase64String(result.Content); 

4
Наверное, это связано с Encoding.
Alex Filipovici

1
Вы знаете, какие «ненужные символы» вставляются?
Джим Мишель

Обновленный код полезен. Теперь нам нужно увидеть строку, которую вы отправляете (т. sЕ. В службе), и полученный контент (т result.content. Е. Вам не нужно публиковать всю строку, только до первого искаженного символа (или, если он все еще слишком длинный) , некоторые подстроки, которые показывают, что было отправлено и что было получено)
Джим Мишель

@JimMischel: да, я заметил, что '/' заменяется на '\ /'
Рохит Верма

@RohitVerma Для замены косой черты это в необработанном HTML-содержимом (Fiddler скажет вам) или в result.Content? Это скажет вам, связана ли проблема с сервером или клиентом.
Джо Энос

Ответы:


94

Проверьте, содержат ли данные вашего изображения некоторую информацию заголовка в начале:

imageCode = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkC...

Это вызовет указанную выше ошибку.

Просто удалите все перед первой запятой включительно, и все готово.

imageCode = "iVBORw0KGgoAAAANSUhEUgAAAMgAAABkC...

1
Как-то была эта проблема. Логика состоит в том, чтобы удалить все после того, как ,если data:присутствует. Бам. Работаю сейчас.
Максим Руиллер

var cleanerBase64 = imageCode.Substring (22); // удалить данные: image / png; base64
mejiamanuel57

3
Немного кода, который поможет ... if (this.imageCode.Contains (',')) this.imageCode = this.imageCode.Substring (this.imageCode.IndexOf (",") + 1, this.imageCode.Length - (this.imageCode.IndexOf (",") + 1));
Тоби Симмерлинг

Я бы использовал: .Split (',') [1]
Verthosa

1
str.Substring(str.LastIndexOf(',') + 1)должен это сделать.
Alisson

65

Очень возможно , это получение преобразуется в модифицированном Base64, где +и /символы заменяются на -и _. См. Http://en.wikipedia.org/wiki/Base64#Implementations_and_history

Если это так, вам нужно изменить его обратно:

string converted = base64String.Replace('-', '+');
converted = converted.Replace('_', '/');

1
Я сделал это .... Спасибо тебе !! Замена символов на соответствующие. Но действительно ли это конкретное решение? я имею в виду, как я могу гарантировать, что для всех файлов этот символ будет заменен?
Рохит Верма

2
@RohitVerma: я не знаю. Вам необходимо выяснить, где меняются эти символы, и определить, вероятно ли изменение каких-либо других символов. Я не знаком с RestSharp, поэтому не могу дать там никаких советов. Если мой ответ ответил на ваш вопрос, его принято отмечать как принятый. (Щелкните галочку рядом с ответом слева.)
Джим Мишель

OMG Спасибо! Это и добавление необходимых символов "=" решило мою проблему. Функция дешифрования в Azure Key Vault REST API нуждается в этом процессе и не документирует его.
used2could 08

33

Мы можем удалить ненужный строковый ввод перед значением.

string convert = hdnImage.Replace("data:image/png;base64,", String.Empty);

byte[] image64 = Convert.FromBase64String(convert);

Это решение сработало для меня. Но это специально для изображений png. Есть ли какой-нибудь обобщенный синтаксис, заменяющий всевозможные расширения изображений?
Каран Десаи

1
я сейчас читаю ваш комментарий. Я не пробую это сделать, но вы можете использовать это: hdnImage.Replace ("data: image / png; base64,", String.Empty) .Replace ("data: image / jpg; base64,", String.Empty) .Replace ( "данные: изображение / bmp; base64,", String.Empty); опять же, я не пытаюсь это сделать. пожалуйста, попробуйте написать для меня. я изменюсь.
Hasan Tuna Oruç

5

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

 var imageParts = model.ImageAsString.Split(',').ToList<string>();
 //Exclude the header from base64 by taking second element in List.
 byte[] Image = Convert.FromBase64String(imageParts[1]);

разделить и перечислить? используйте скорее IndexOf и подстроку
Эммануэль Глейзер

см. demeranville.com/… и вопрос также размещен здесь: stackoverflow.com/questions/35388181/…
Эммануэль Глейзер

4

Поскольку вы возвращаете строку как JSON, эта строка будет включать открывающую и закрывающую кавычки в необработанном ответе. Ваш ответ, вероятно, должен выглядеть так:

"abc123XYZ=="

или что-то еще ... Вы можете попробовать подтвердить это с помощью Fiddler.

Я предполагаю, что result.Contentэто необработанная строка, включая кавычки. В этом случае result.Contentперед использованием необходимо выполнить десериализацию.


вы правы, сюда входит "", но дело в том, что помимо добавления этих кавычек заменяются и другие символы.
Рохит Верма

Десериализация этой строки с помощью сериализатора JSON позаботится как о кавычках, так и о экранированной косой черте. Некоторые сериализаторы JSON делают экранирование косых черт с помощью обратной косой черты - использование десериализатора превратит \ / обратно в простой /, так что вы получите действительный base-64. Поскольку вы получаете JSON, всегда полезно правильно проанализировать этот JSON, даже если это простая строка.
Джо Энос

3

Я организовал аналогичный контекст, как вы описали, и столкнулся с той же ошибкой. Мне удалось заставить его работать, удалив в "начале и в конце контента и заменив \/на /.

Вот фрагмент кода:

var result = client.Execute(request);
var response = result.Content
    .Substring(1, result.Content.Length - 2)
    .Replace(@"\/","/");
byte[] d = Convert.FromBase64String(response);

В качестве альтернативы вы можете рассмотреть возможность использования XML для формата ответа:

[WebGet(UriTemplate = "ReadFile/Convert", ResponseFormat = WebMessageFormat.Xml)]  
public string ExportToExcel() { //... }

На стороне клиента:

request.AddHeader("Accept", "application/xml");
request.AddHeader("Content-Type", "application/xml");
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/xml"; };

var result = client.Execute(request);
var doc = new System.Xml.XmlDocument();
doc.LoadXml(result.Content);
var xml = doc.InnerText;
byte[] d = Convert.FromBase64String(xml);

3
var spl = item.Split('/')[1];
var format =spl.Split(';')[0];           
stringconvert=item.Replace($"data:image/{format};base64,",String.Empty);

7
Хотя этот код может решить проблему, хороший ответ должен также объяснить, что он делает и как помогает.
BDL

2

Удаляем ненужную строку через Regex

Regex regex=new Regex(@"^[\w/\:.-]+;base64,");
base64File=regex.Replace(base64File,string.Empty);

1

Как сказал Алекс Филиповичи, проблема заключалась в неправильной кодировке. Файл, который я прочитал, был UTF-8-BOMи вызвал вышеуказанную ошибку Convert.FromBase64String(). Переход на UTF-8действительно работал без проблем.


1

И иногда это начиналось с двойных кавычек, в большинстве случаев, когда вы вызываете API из dotNetCore 2 для получения файла

string string64 = string64.Replace(@"""", string.Empty);
byte[] bytes = Convert.ToBase64String(string64);

1
Невозможно преобразовать строку в байт []
Urasquirrel 06

1

Вероятно, строка будет такой, как эта data:image/jpeg;base64,/9j/4QN8RXh... Первая разделить /и получить второй токен.

var StrAfterSlash = Face.Split('/')[1];

Затем разделите на ;и получите первый токен, который будет форматом. В моем случае это jpeg.

var ImageFormat =StrAfterSlash.Split(';')[0];

Затем удалите строчку data:image/jpeg;base64,для собранного формата

CleanFaceData=Face.Replace($"data:image/{ImageFormat };base64,",string.Empty);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.