อินพุตไม่ใช่สตริง Base-64 ที่ถูกต้องเนื่องจากมีอักขระ 64 ที่ไม่ใช่ฐาน


98

ฉันมีบริการ REST ที่อ่านไฟล์และส่งไปยังแอปพลิเคชันคอนโซลอื่นหลังจากแปลงเป็นอาร์เรย์ไบต์แล้วเป็นสตริง Base64 ส่วนนี้ใช้งานได้ แต่เมื่อได้รับสตรีมเดียวกันที่แอปพลิเคชันจะได้รับการจัดการและไม่ใช่สตริง Base64 ที่ถูกต้องอีกต่อไป มีการนำตัวละครขยะบางตัวเข้าสู่สตรีม

ข้อยกเว้นที่ได้รับเมื่อแปลงสตรีมกลับเป็นไบต์คือ

อินพุตไม่ใช่สตริง Base-64 ที่ถูกต้องเนื่องจากมีอักขระที่ไม่ใช่ฐาน 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
คุณรู้หรือไม่ว่ามี "อักขระขยะ" อะไรบ้าง?
Jim Mischel

รหัสที่อัปเดตมีประโยชน์ ตอนนี้เราจำเป็นต้องเห็นสตริงที่คุณส่ง (เช่นsในบริการ) และเนื้อหาที่ได้รับ (กล่าวคือresult.contentคุณไม่จำเป็นต้องโพสต์สตริงทั้งหมดเพียงแค่อักขระที่ยุ่งเหยิงตัวแรก (หรือหากยังยาวเกินไป สตริงย่อยบางรายการที่แสดงสิ่งที่ส่งและสิ่งที่ได้รับ)
Jim Mischel

@JimMischel ใช่ฉันสังเกตเห็นว่า '/' ถูกแทนที่ด้วย '\ /'
Rohit Verma

@RohitVerma สำหรับการแทนที่ด้วยเครื่องหมายทับนั้นอยู่ในเนื้อหา HTML ดิบ (Fiddler จะบอกคุณ) หรือในresult.Content? ซึ่งจะบอกคุณว่าปัญหาเกิดจากเซิร์ฟเวอร์หรือไคลเอนต์
Joe Enos

คำตอบ:


94

ตรวจสอบว่าข้อมูลรูปภาพของคุณมีข้อมูลส่วนหัวในตอนต้นหรือไม่:

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

ซึ่งจะทำให้เกิดข้อผิดพลาดข้างต้น

เพียงแค่ลบทุกอย่างที่อยู่ตรงหน้าและใส่เครื่องหมายจุลภาคตัวแรกคุณก็พร้อมใช้งาน

imageCode = "iVBORw0KGgoAAAANSUhEUgAAAMgAAABkC...

1
มีปัญหานี้แน่นอน ลอจิกคือการลบทุกอย่างหลังจาก,ถ้าdata:เป็นปัจจุบัน แบม. กำลังทำงานอยู่.
Maxime Rouiller

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));
Toby Simmerling

ฉันจะใช้ :.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
ฉันทำได้แล้ว .... ขอบคุณมาก !! แทนที่อักขระด้วยอักขระที่เหมาะสม แต่นี่คือทางออกที่เป็นรูปธรรมหรือไม่? ฉันหมายถึงฉันจะรับประกันได้อย่างไรว่าสำหรับไฟล์ทั้งหมดนี้จะเป็นอักขระที่จะถูกแทนที่
Rohit Verma

2
@RohitVerma: ฉันไม่รู้ คุณต้องค้นหาว่าตัวละครเหล่านั้นมีการเปลี่ยนแปลงที่ใดและพิจารณาว่ามีแนวโน้มที่จะเปลี่ยนอักขระอื่น ๆ หรือไม่ ฉันไม่คุ้นเคยกับ RestSharp จึงไม่สามารถให้คำแนะนำที่นั่นได้ หากคำตอบของฉันตอบคำถามของคุณได้คุณควรทำเครื่องหมายว่าเป็นคำตอบที่ยอมรับ (คลิกเครื่องหมายถูกข้างคำตอบทางด้านซ้าย)
Jim Mischel

OMG ขอบคุณ! สิ่งนี้และการเพิ่มอักขระ padding "=" ที่จำเป็นช่วยแก้ปัญหาของฉันได้ ฟังก์ชันถอดรหัสใน Key Vault REST API ของ Azure ต้องการกระบวนการนี้และไม่ได้จัดทำเป็นเอกสาร
used2could

33

เราสามารถลบอินพุตสตริงที่ไม่จำเป็นออกด้านหน้าค่าได้

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

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

วิธีนี้ใช้ได้ผลสำหรับฉัน แต่นี่เป็นภาพ png โดยเฉพาะ มีไวยากรณ์ทั่วไปที่แทนที่ส่วนขยายรูปภาพทุกชนิดหรือไม่?
Karan Desai

1
ฉันอ่านความคิดเห็นของคุณตอนนี้ ฉันไม่ได้ลอง แต่คุณสามารถใช้สิ่งนี้: hdnImage.Replace ("data: image / png; base64,", String.Empty) แทนที่ ("data: image / jpg; base64,", String.Empty) แทนที่ ( "data: image / 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 และสตริงย่อย
Emmanuel Gleizer

ดูdemeranville.com/…และโพสต์คำถามได้ที่นี่: stackoverflow.com/questions/35388181/…
Emmanuel Gleizer

4

เนื่องจากคุณส่งคืนสตริงเป็น JSON สตริงนั้นจะรวมเครื่องหมายคำพูดเปิดและปิดในการตอบกลับดิบ ดังนั้นคำตอบของคุณควรมีลักษณะดังนี้:

"abc123XYZ=="

หรืออะไรก็ได้ ... คุณสามารถลองยืนยันกับ Fiddler

ฉันเดาว่าresult.Contentเป็นสตริงดิบรวมถึงเครื่องหมายคำพูด หากเป็นเช่นนั้นคุณresult.Contentจะต้องทำการ deserialized ก่อนจึงจะใช้งานได้


คุณถูกต้องซึ่งรวมถึง "" แต่ประเด็นนี้ก็คือนอกเหนือจากการเพิ่มเครื่องหมายคำพูดเหล่านี้แล้วยังมีการแทนที่อักขระอื่น ๆ ด้วย
Rohit Verma

การแยกสายอักขระนั้นโดยใช้ซีเรียลไลเซอร์ JSON จะดูแลทั้งเครื่องหมายคำพูดและเครื่องหมายทับ การหลีกเลี่ยงเครื่องหมายทับด้วยแบ็กสแลชเป็นสิ่งที่อนุกรมของ JSON บางตัวทำ - การใช้ deserializer จะเปลี่ยน \ / กลับเป็นธรรมดา / เพื่อให้คุณได้รับฐาน -64 ที่ถูกต้อง เนื่องจากคุณได้รับ JSON คุณควรแยกวิเคราะห์ JSON นั้นอย่างถูกต้องแม้ว่าจะเป็นเพียงสตริงธรรมดาก็ตาม
Joe Enos

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


1

ดังที่Alex Filipoviciกล่าวถึงปัญหานี้เป็นการเข้ารหัสที่ไม่ถูกต้อง ไฟล์ที่ผมอ่านในเป็นและโยนผิดพลาดดังกล่าวในUTF-8-BOM Convert.FromBase64String()การเปลี่ยนไปใช้UTF-8งานได้โดยไม่มีปัญหา


1

และบางครั้งก็เริ่มต้นด้วยเครื่องหมายคำพูดคู่ซึ่งส่วนใหญ่เมื่อคุณเรียก API จาก dotNetCore 2 เพื่อรับไฟล์

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

1
ไม่สามารถแปลงจากสตริงเป็นไบต์ []
Urasquirrel

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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.