A entrada não é uma string Base-64 válida, pois contém um caractere não-base 64

105

Eu tenho um serviço REST que lê um arquivo e o envia para outro aplicativo de console depois de convertê-lo em uma matriz de bytes e, em seguida, em uma string Base64. Essa parte funciona, mas quando o mesmo fluxo é recebido no aplicativo, ele é manipulado e não é mais uma string Base64 válida. Alguns personagens inúteis estão sendo introduzidos no fluxo.

A exceção recebida ao converter o fluxo de volta para Byte é

A entrada não é uma string Base-64 válida, pois contém um caractere não base 64, mais de dois caracteres de preenchimento ou um caractere de espaço não em branco entre os caracteres de preenchimento

Em serviço:

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

Na aplicação:

       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); 
Rohit Verma
fonte
4
Provavelmente isso tem a ver com Encoding.
Alex Filipovici
1
Você sabe quais "caracteres inúteis" estão sendo inseridos?
Jim Mischel
O código atualizado é útil. Agora precisamos ver a string que você envia (ou seja, sno serviço) e o conteúdo que é recebido (ou seja, result.contentvocê não precisa postar a string inteira, apenas até o primeiro caractere mutilado (ou, se ainda for muito longo , algumas substrings que mostram o que foi enviado e o que foi recebido.
Jim Mischel
@JimMischel sim, notei que '/' está sendo substituído por '\ /'
Rohit Verma
@RohitVerma Para a barra sendo substituída, ela está no conteúdo HTML bruto (o Fiddler dirá a você) ou em result.Content? Isso dirá se o problema está no servidor ou no cliente.
Joe Enos

Respostas:

100

Verifique se os dados da imagem contêm algumas informações de cabeçalho no início:

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

Isso causará o erro acima.

Basta remover tudo antes e inclusive a primeira vírgula, e pronto.

imageCode = "iVBORw0KGgoAAAANSUhEUgAAAMgAAABkC...
bendecko
fonte
1
Tive exatamente esse problema de alguma forma. A lógica é remover tudo após ,se data:estiver presente. Bam. Trabalhando agora.
Maxime Rouiller de
var cleanerBase64 = imageCode.Substring (22); // remover dados: image / png; base64
mejiamanuel57
3
Apenas um pouco de código para ajudar ...... if (this.imageCode.Contains (',')) this.imageCode = this.imageCode.Substring (this.imageCode.IndexOf (",") + 1, this.imageCode.Length - (this.imageCode.IndexOf (",") + 1));
Toby Simmerling
Eu usaria: .Split (',') [1]
Verthosa
1
str.Substring(str.LastIndexOf(',') + 1)deve fazer isso.
Alisson
66

Muito provavelmente, ele está sendo convertido para um Base64 modificado, onde os caracteres +e /são alterados para -e _. Consulte http://en.wikipedia.org/wiki/Base64#Implementations_and_history

Se for esse o caso, você precisa alterá-lo de volta:

string converted = base64String.Replace('-', '+');
converted = converted.Replace('_', '/');
Jim Mischel
fonte
1
Eu consegui fazer isso .... Graças a você !! Substituindo os personagens pelos apropriados. Mas esta é uma solução concreta? quero dizer, como posso garantir que, para todos os arquivos, esse será o caractere a ser substituído?
Rohit Verma
2
@RohitVerma: Não sei. Você precisa descobrir onde esses personagens estão sendo alterados e determinar se há probabilidade de alterar qualquer outro personagem. Não estou familiarizado com o RestSharp, então não posso oferecer nenhum conselho. Se minha resposta respondeu à sua pergunta, é comum marcá-la como a resposta aceita. (Clique na marca de seleção ao lado da resposta à esquerda.)
Jim Mischel
OMG, obrigado! Isso e a adição dos caracteres "=" de preenchimento necessários resolveram meu problema. A função de descriptografia na API REST do Key Vault do Azure precisa desse processo e não o documenta.
usado2 poderia
35

Podemos remover a entrada de string desnecessária na frente do valor.

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

byte[] image64 = Convert.FromBase64String(convert);
Hasan Tuna Oruç
fonte
Essa solução funcionou para mim. Mas isso é especificamente para imagens PNG. Existe alguma sintaxe generalizada que substitui todos os tipos de extensões de imagem?
Karan Desai
1
eu li seu comentário agora. eu não tente fazer isso, mas você pode usar isso: hdnImage.Replace ("data: image / png; base64,", String.Empty) .Replace ("data: image / jpg; base64,", String.Empty) .Replace ( "dados: imagem / bmp; base64,", String.Empty); novamente, eu não tento isso. por favor, tente escrever para mim. Eu mudarei.
Hasan Tuna Oruç
5

Para o caso de você não saber o tipo de imagem enviada, basta remover o base64cabeçalho:

 var imageParts = model.ImageAsString.Split(',').ToList<string>();
 //Exclude the header from base64 by taking second element in List.
 byte[] Image = Convert.FromBase64String(imageParts[1]);
Mahdi Alkhatib
fonte
dividir e para listar? em vez disso, use IndexOf e substring
Emmanuel Gleizer
consulte demeranville.com/… e a pergunta também está postada aqui: stackoverflow.com/questions/35388181/…
Emmanuel Gleizer
4

Como você está retornando uma string como JSON, essa string incluirá as aspas de abertura e fechamento na resposta bruta. Portanto, sua resposta provavelmente deve ser assim:

"abc123XYZ=="

ou qualquer coisa ... Você pode tentar confirmar isso com o Fiddler.

Meu palpite é que result.Contenté a string bruta, incluindo as aspas. Se for esse o caso, result.Contentserá necessário desserializar antes de poder usá-lo.

Joe Enos
fonte
você está correto, isso inclui "", mas o ponto aqui é que, além da adição dessas aspas, outros caracteres também estão sendo substituídos.
Rohit Verma
A desserialização dessa string usando um serializador JSON cuidará das aspas e da barra de escape. Escapar suas barras com uma barra invertida é algo que alguns serializadores JSON fazem - usar um desserializador irá transformar \ / novamente em simples / para que você obtenha uma base 64 válida. Como você está recebendo JSON, é sempre uma boa ideia analisar esse JSON corretamente, mesmo que seja apenas uma string simples.
Joe Enos
3

Organizei um contexto semelhante ao que você descreveu e encontrei o mesmo erro. Consegui fazê-lo funcionar removendo o "do início e o fim do conteúdo e substituindo \/por /.

Aqui está o snippet 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, você pode considerar o uso de XML para o formato de resposta:

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

Do lado do 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);
Alex Filipovici
fonte
3
var spl = item.Split('/')[1];
var format =spl.Split(';')[0];           
stringconvert=item.Replace($"data:image/{format};base64,",String.Empty);
Mostafa Kazemi
fonte
7
Embora esse código possa resolver o problema, uma boa resposta também deve explicar o que o código faz e como isso ajuda.
BDL
2

Como Alex Filipovici mencionou, o problema era uma codificação errada. O arquivo que li era UTF-8-BOMe gerava o erro acima Convert.FromBase64String(). Mudar para UTF-8funcionou sem problemas.

testando
fonte
2

Remova a string desnecessária por meio do Regex

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

E algumas vezes começava com aspas duplas, na maioria das vezes quando você chama a API do dotNetCore 2 para obter o arquivo

string string64 = string64.Replace(@"""", string.Empty);
byte[] bytes = Convert.ToBase64String(string64);
user193679
fonte
1
Não é possível converter de string para byte []
Urasquirrel
1

Provavelmente a string seria assim data:image/jpeg;base64,/9j/4QN8RXh... Primeira divisão para /e obter o segundo token.

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

Em seguida, divida ;e obtenha o primeiro token, que será o formato. No meu caso, é jpeg.

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

Em seguida, remova a linha data:image/jpeg;base64,para o formato coletado

CleanFaceData=Face.Replace($"data:image/{ImageFormat };base64,",string.Empty);
DevLoverUmar
fonte
0

Recebo este erro porque um campo era varbinary na tabela sqlserver em vez de varchar .

M Komaei
fonte