Die Eingabe ist keine gültige Base-64-Zeichenfolge, da sie ein Nicht-Base-64-Zeichen enthält

92

Ich habe einen REST-Dienst, der eine Datei liest und an eine andere Konsolenanwendung sendet, nachdem sie in ein Byte-Array und dann in eine Base64-Zeichenfolge konvertiert wurde. Dieser Teil funktioniert, aber wenn derselbe Stream in der Anwendung empfangen wird, wird er manipuliert und ist keine gültige Base64-Zeichenfolge mehr. Einige Junk-Charaktere werden in den Stream eingeführt.

Die Ausnahme, die beim Konvertieren des Streams zurück in Byte empfangen wird, ist

Die Eingabe ist keine gültige Base-64-Zeichenfolge, da sie ein Nicht-Base-64-Zeichen, mehr als zwei Füllzeichen oder ein nicht Leerzeichen unter den Füllzeichen enthält

Im Service:

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

Bei der Anwendung:

       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
quelle
4
Wahrscheinlich hat das damit zu tun Encoding.
Alex Filipovici
1
Wissen Sie, welche "Junk-Zeichen" eingefügt werden?
Jim Mischel
Der aktualisierte Code ist hilfreich. Jetzt müssen wir die Zeichenfolge sehen, die Sie senden (dh sim Dienst), und den Inhalt, der empfangen wird (dh result.contentSie müssen nicht die gesamte Zeichenfolge veröffentlichen, sondern nur bis zum ersten verstümmelten Zeichen (oder, wenn das noch zu lang ist) , einige Teilzeichenfolgen, die zeigen, was gesendet und was empfangen wurde)
Jim Mischel
@ JimMischel Ja, ich habe bemerkt, dass '/' durch '\ /' ersetzt wird
Rohit Verma
@RohitVerma Wenn der Schrägstrich ersetzt wird, ist das in den rohen HTML-Inhalten (Fiddler wird es Ihnen sagen) oder in result.Content? Hier erfahren Sie, ob das Problem beim Server oder beim Client liegt.
Joe Enos

Antworten:

83

Überprüfen Sie, ob Ihre Bilddaten zu Beginn einige Header-Informationen enthalten:

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

Dies führt zu dem oben genannten Fehler.

Entfernen Sie einfach alles vor und einschließlich des ersten Kommas, und schon kann es losgehen.

imageCode = "iVBORw0KGgoAAAANSUhEUgAAAMgAAABkC...
bendecko
quelle
Hatte genau dieses Problem irgendwie. Die Logik ist alles zu entfernen , nachdem ,wenn data:vorhanden ist. Bam. Arbeite jetzt.
Maxime Rouiller
var CleanerBase64 = imageCode.Substring (22); // Daten entfernen: image / png; base64
mejiamanuel57
3
Nur ein bisschen Code, um zu helfen ...... if (this.imageCode.Contains (',')) this.imageCode = this.imageCode.Substring (this.imageCode.IndexOf (",") + 1, this.imageCode.Length - (this.imageCode.IndexOf (",") + 1));
Toby Simmerling
Ich würde verwenden: .Split (',') [1]
Verthosa
str.Substring(str.LastIndexOf(',') + 1)Sollte es tun.
Alisson
63

Sehr wahrscheinlich wird es zu einem modifizierten Base64 umgewandelt zu werden , wo die +und /Zeichen geändert werden -und _. Siehe http://en.wikipedia.org/wiki/Base64#Implementations_and_history

Wenn dies der Fall ist, müssen Sie es zurück ändern:

string converted = base64String.Replace('-', '+');
converted = converted.Replace('_', '/');
Jim Mischel
quelle
1
Ich habe das geschafft ... Danke an dich !! Ersetzen Sie die Zeichen durch die entsprechenden. Aber ist das eine konkrete Lösung? Ich meine, wie kann ich garantieren, dass für alle Dateien dies das Zeichen ist, das ersetzt werden soll?
Rohit Verma
2
@RohitVerma: Ich weiß es nicht. Sie müssen herausfinden, wo diese Zeichen geändert werden, und feststellen, ob wahrscheinlich andere Zeichen geändert werden. Ich bin mit RestSharp nicht vertraut, daher kann ich dort keine Ratschläge geben. Wenn meine Antwort Ihre Frage beantwortet hat, ist es üblich, sie als akzeptierte Antwort zu markieren. (Klicken Sie auf das Häkchen neben der Antwort auf der linken Seite.)
Jim Mischel
OMG Danke! Dies und das Hinzufügen der erforderlichen Auffüllzeichen "=" lösten mein Problem. Die Entschlüsselungsfunktion in der Key Vault-REST-API von Azure benötigt diesen Prozess und dokumentiert ihn nicht.
used2could
30

Wir können unnötige Zeichenfolgeneingaben vor dem Wert entfernen.

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

byte[] image64 = Convert.FromBase64String(convert);
Hasan Thunfisch Oruç
quelle
Diese Lösung hat bei mir funktioniert. Dies ist jedoch speziell für PNG-Bilder. Gibt es eine verallgemeinerte Syntax, die alle Arten von Bilderweiterungen ersetzt?
Karan Desai
1
Ich habe deinen Kommentar jetzt gelesen. Ich versuche dies nicht, aber Sie können dies verwenden: hdnImage.Replace ("Daten: image / png; base64,", String.Empty) .Replace ("Daten: image / jpg; base64,", String.Empty) .Replace ( "data: image / bmp; base64", String.Empty); wieder versuche ich das nicht. Bitte versuchen Sie, für mich zu schreiben. Ich werde mich verändern.
Hasan Thunfisch Oruç
5

Nur für den Fall, dass Sie den Typ des hochgeladenen Bildes nicht kennen und nur dessen base64Kopfzeile entfernen müssen :

 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
quelle
teilen und auflisten? Verwenden Sie lieber IndexOf und Teilzeichenfolge
Emmanuel Gleizer
siehe demeranville.com/… und die Frage wird auch hier gepostet: stackoverflow.com/questions/35388181/…
Emmanuel Gleizer
4

Da Sie eine Zeichenfolge als JSON zurückgeben, enthält diese Zeichenfolge die öffnenden und schließenden Anführungszeichen in der Rohantwort. Ihre Antwort sollte also wahrscheinlich so aussehen:

"abc123XYZ=="

oder was auch immer ... Sie können versuchen, dies mit Fiddler zu bestätigen.

Ich vermute, dass dies die Rohzeichenfolge ist result.Content, einschließlich der Anführungszeichen. Wenn dies der Fall ist, result.Contentmuss es deserialisiert werden, bevor Sie es verwenden können.

Joe Enos
quelle
Sie haben Recht, dies schließt "" ein, aber der Punkt hier ist, dass neben dem Hinzufügen dieser Anführungszeichen auch andere Zeichen ersetzt werden.
Rohit Verma
Durch Deserialisieren dieser Zeichenfolge mit einem JSON-Serializer werden sowohl die Anführungszeichen als auch der maskierte Schrägstrich berücksichtigt. Es ist etwas, was einige JSON-Serializer tun, wenn Sie Ihre Schrägstriche mit einem Backslash umgehen. Wenn Sie einen Deserializer verwenden, wird \ / back einfach /, sodass Sie eine gültige Basis-64 erhalten. Da Sie JSON erhalten, ist es immer eine gute Idee, JSON richtig zu analysieren, auch wenn es sich nur um eine einfache Zeichenfolge handelt.
Joe Enos
3

Ich habe einen ähnlichen Kontext wie Sie beschrieben und den gleichen Fehler festgestellt. Ich schaffte es zum Laufen zu bringen , indem die Entfernung "von dem Anfang und das Ende des Inhalts und durch den Ersatz \/mit /.

Hier ist das Code-Snippet:

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

Alternativ können Sie XML für das Antwortformat verwenden:

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

Auf der Client-Seite:

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
quelle
3
var spl = item.Split('/')[1];
var format =spl.Split(';')[0];           
stringconvert=item.Replace($"data:image/{format};base64,",String.Empty);
Mostafa Kazemi
quelle
6
Obwohl dieser Code das Problem lösen könnte, sollte eine gute Antwort auch erklären, was der Code tut und wie er hilft.
BDL
1

Wie Alex Filipovici erwähnte, war das Problem eine falsche Codierung. Die Datei, die ich eingelesen habe, war UTF-8-BOMund warf den obigen Fehler auf Convert.FromBase64String(). Der Wechsel zu UTF-8hat ohne Probleme funktioniert.

testen
quelle
1

Und manchmal begann es mit doppelten Anführungszeichen, meistens, wenn Sie die API von dotNetCore 2 aus aufrufen, um eine Datei abzurufen

string string64 = string64.Replace(@"""", string.Empty);
byte[] bytes = Convert.ToBase64String(string64);
user193679
quelle
1
Kann nicht von Zeichenfolge zu Byte konvertieren []
Urasquirrel