La entrada no es una cadena Base-64 válida ya que contiene un carácter no base 64


98

Tengo un servicio REST que lee un archivo y lo envía a otra aplicación de consola después de convertirlo en una matriz de bytes y luego en una cadena Base64. Esta parte funciona, pero cuando se recibe el mismo flujo en la aplicación, se manipula y ya no es una cadena Base64 válida. Algunos personajes basura se están introduciendo en la corriente.

La excepción recibida al convertir la transmisión de nuevo a Byte es

La entrada no es una cadena Base-64 válida, ya que contiene un carácter no base 64, más de dos caracteres de relleno o un carácter de espacio en blanco entre los caracteres de relleno

En servicio:

[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;
  }

En la aplicación:

       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
Probablemente esto tenga que ver con Encoding.
Alex Filipovici

1
¿Sabes qué "caracteres basura" se están insertando?
Jim Mischel

El código actualizado es útil. Ahora necesitamos ver la cadena que envías (es decir, sen el servicio) y el contenido que se recibe (es decir result.content, no necesitas publicar toda la cadena, solo hasta el primer carácter mutilado (o, si aún es demasiado largo) , algunas subcadenas que muestran lo que se envió y lo que se recibió)
Jim Mischel

@JimMischel sí, noté que '/' está siendo reemplazado por '\ /'
Rohit Verma

@RohitVerma Para la barra inclinada que se reemplaza, ¿está en el contenido HTML sin procesar (Fiddler te lo dirá), o en result.Content? Eso le dirá si el problema está en el servidor o en el cliente.
Joe Enos

Respuestas:


94

Verifique si los datos de su imagen contienen información de encabezado al principio:

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

Esto provocará el error anterior.

Simplemente elimine todo lo que esté delante de la primera coma incluida, y listo.

imageCode = "iVBORw0KGgoAAAANSUhEUgAAAMgAAABkC...

1
Tenía este problema exacto de alguna manera. La lógica es eliminar todo lo que después de ,si data:está presente. Bam. Trabajando ahora.
Maxime Rouiller

var cleanerBase64 = imageCode.Substring (22); // eliminar datos: image / png; base64
mejiamanuel57

3
Solo un poco de código para ayudar ...... si (this.imageCode.Contains (',')) this.imageCode = this.imageCode.Substring (this.imageCode.IndexOf (",") + 1, this.imageCode.Length - (this.imageCode.IndexOf (",") + 1));
Toby Simmerling

Yo usaría: .Split (',') [1]
Verthosa

1
str.Substring(str.LastIndexOf(',') + 1)Deberías hacerlo.
Alisson

65

Es muy posible que se convierta en un Base64 modificado, donde los caracteres +y /se cambian a -y _. Ver http://en.wikipedia.org/wiki/Base64#Implementations_and_history

Si ese es el caso, debe volver a cambiarlo:

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

1
Hice esto ... ¡¡Gracias a ti !! Reemplazando los personajes por los adecuados. ¿Pero es esta una solución concreta? Quiero decir, ¿cómo puedo garantizar que para todos los archivos este será el carácter que se reemplazará?
Rohit Verma

2
@RohitVerma: No lo sé. Debe averiguar dónde se están modificando esos personajes y determinar si es probable que cambie a otros personajes. No estoy familiarizado con RestSharp, por lo que no puedo ofrecer ningún consejo allí. Si mi respuesta respondió a su pregunta, es costumbre marcarla como la respuesta aceptada. (Haga clic en la marca de verificación junto a la respuesta a la izquierda.)
Jim Mischel

¡Dios mío, gracias! Esto y agregar los caracteres de relleno necesarios "=" resolvieron mi problema. La función de descifrado en la API REST de Key Vault de Azure necesita este proceso y no lo documenta.
used2could

33

Podemos eliminar la entrada de cadena innecesaria delante del valor.

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

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

Esta solución funcionó para mí. Pero esto es específicamente para imágenes png. ¿Existe alguna sintaxis generalizada que reemplace todo tipo de extensiones de imagen?
Karan Desai

1
leí tu comentario ahora. No intento esto, pero puedes usar esto: hdnImage.Replace ("data: image / png; base64,", String.Empty) .Replace ("data: image / jpg; base64,", String.Empty) .Replace ( "datos: imagen / bmp; base64,", String.Empty); de nuevo, no intento esto. por favor intente escribir por mí. cambiaré.
Hasan Tuna Oruç

5

En caso de que no sepa el tipo de imagen cargada, y solo necesita eliminar su base64encabezado:

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

split y To List? use en lugar IndexOf y substring
Emmanuel Gleizer

consulte demeranville.com/… y la pregunta también se publica aquí: stackoverflow.com/questions/35388181/…
Emmanuel Gleizer

4

Dado que está devolviendo una cadena como JSON, esa cadena incluirá las comillas de apertura y cierre en la respuesta sin procesar. Entonces, su respuesta probablemente debería verse así:

"abc123XYZ=="

o lo que sea ... Puedes intentar confirmar esto con Fiddler.

Supongo que result.Contentes la cadena sin formato, incluidas las comillas. Si ese es el caso, result.Contentserá necesario deserializarlo antes de poder usarlo.


tiene razón, esto incluye "", pero el punto aquí es que, aparte de la adición de estas comillas, también se reemplazan otros caracteres.
Rohit Verma

La deserialización de esa cadena con un serializador JSON se encargará tanto de las comillas como de la barra inclinada. Escapar de las barras diagonales con una barra invertida es algo que hacen algunos serializadores JSON: el uso de un deserializador convertirá \ / de nuevo en simple / para que obtenga una base 64 válida. Dado que está recibiendo JSON, siempre es una buena idea analizar ese JSON correctamente, incluso si es solo una cadena simple.
Joe Enos

3

Arreglé un contexto similar al que describiste y enfrenté el mismo error. Logré que funcionara eliminando el "del principio y el final del contenido y reemplazándolo \/por /.

Aquí está el fragmento de código:

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

Como alternativa, podría considerar usar XML para el formato de respuesta:

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

Del lado del cliente:

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
Aunque este código podría resolver el problema, una buena respuesta también debería explicar qué hace el código y cómo ayuda.
BDL

2

Eliminar la cadena innecesaria a través de Regex

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

1

Como mencionó Alex Filipovici, el problema era una codificación incorrecta. El archivo que leí era UTF-8-BOMy arrojé el error anterior Convert.FromBase64String(). El cambio a UTF-8funcionó sin problemas.


1

Y algunas veces comenzó con comillas dobles, la mayoría de las veces cuando llama a API desde dotNetCore 2 para obtener el archivo

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

1
No se puede convertir de cadena a byte []
Urasquirrel

1

Probablemente la cadena sería así data:image/jpeg;base64,/9j/4QN8RXh... Primero dividir /y obtener el segundo token.

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

Luego, divida ;y obtenga el primer token que será el formato. En mi caso es jpeg.

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

Luego elimine la línea data:image/jpeg;base64,para el formato recopilado

CleanFaceData=Face.Replace($"data:image/{ImageFormat };base64,",string.Empty);
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.