none
Base64 codierter JSON-String in Binary umwandeln RRS feed

  • Frage

  • Hallo,
    von einer Javascriptfunktion wird an einen WebService ein Base64 String übergeben.

            function fnUploadFile()
            {
                var file = document.getElementById('FileUpload').files[0];
                var reader = new FileReader();
                var retValue = "";
                var fname = file.name;
                reader.readAsDataURL(file);
                reader.onload = function ()
                {
                    retValue = window.btoa(reader.result).toString(); 
                    Url = "/Services/DateiService.svc/fnUploadFile";
                    Data = '{ "strFileName": "' + fname + '", "strBlob": "' + retValue + '"}';
                    console.log(Data);
                    var responsedata = CallService(null, "nix");
                };
                reader.onerror = function (error)
                {
                    retValue = error;
                    console.log('Error: ', error);
                };
            }

    Inhalt der Textdatei: 

    Irgend ein Text zum Testen.
    Blablablabla


    Nun soll das wieder in eine Datei umgewandelt und abgespeichert werden.

        <OperationContract()>
        <WebInvoke(Method:="POST", RequestFormat:=WebMessageFormat.Json, ResponseFormat:=WebMessageFormat.Json)>
        Public Function fnGetFile(strBlob As String, strFileName As String) As String
    
            Dim bytes() As Byte = Convert.FromBase64String(strBlob)
            Dim strPath As String = Server.MapPath("/Storage/" + strFileName)
    
            File.WriteAllBytes(strPath, bytes)
        End Function

    Übergeben wird als Base64-String:

    ZGF0YTp0ZXh0L3BsYWluO2Jhc2U2NCxTWEpuWlc1a0lHVnBiaUJVWlhoMElIcDFiU0JVWlhOMFpXNHVEUXBDYkdGaWJHRmliR0ZpYkdFPQ==

    In der Datei steht dann allerdings folgendes:

    data:text/plain;base64,SXJnZW5kIGVpbiBUZXh0IHp1bSBUZXN0ZW4uDQpCbGFibGFibGFibGE=

    Geb ich z.B. diesen String direkt im Browser ein, so wird wieder das korekte Ergebnis angezeigt.
    Könnte mir da evtl.jemand weiterhelfen?

    Und noch eine Frage: Bis zu welcher Größe macht es denn Sinn eine Datei so zu übergeben?


    Viele Grüße, Volker


    • Bearbeitet Volker S Freitag, 13. April 2018 08:42
    Freitag, 13. April 2018 08:01

Antworten

  • Hallo Volker,

    der Inhalt kommt, da Du die Datei per:

    reader.readAsDataURL(file);

    einliest. Du musst den Teil:

    data:text/plain;base64,

    entfernen und den Rest dann per Convert.FromBase64String zurückwandeln.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Freitag, 13. April 2018 09:06
    Moderator

Alle Antworten

  • Hallo Volker,

    der Inhalt kommt, da Du die Datei per:

    reader.readAsDataURL(file);

    einliest. Du musst den Teil:

    data:text/plain;base64,

    entfernen und den Rest dann per Convert.FromBase64String zurückwandeln.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Freitag, 13. April 2018 09:06
    Moderator
  • Hallo Stefan,
    vielen Dank für dein Interesse.

    Der "data:text/plain;base64," Teil wird doch automatisch durch
    window.btoa(reader.result)
    angestellt.
    Übergebe ich nur das reine result vom reader, dann weigert sich die Convert.FromBase64String-Funktion zur Konvertierung.

    Oder verstehe ich dich falsch?


    Viele Grüße, Volker


    • Bearbeitet Volker S Freitag, 13. April 2018 09:26
    Freitag, 13. April 2018 09:25
  • Vergiss es.

    Ich muss 

    reader.readAsBinaryString(file);

    benutzen, dann klappt es auch.

    Danke dir für deine Unterstützung.


    Viele Grüße, Volker


    • Bearbeitet Volker S Freitag, 13. April 2018 09:33
    Freitag, 13. April 2018 09:29
  • Hallo Volker,

    nö. window.btoa codiert den ganzen String nochmal als Base64. Das ist in dem Fall unnötig, da readAsDataURL das auch schon macht. Alternativ kannst Du auch serverseitig erstmal den übergebenen String decodieren, dann:

    data:text/plain;base64,

    entfernen und den Rest nochmal per FromBase64 String decodieren.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Freitag, 13. April 2018 09:31
    Moderator
  • Hallo Volker,

    ich habe das explizit nicht geschrieben, da readAsBinaryString keine Standardmethode ist und nicht bei allen Usern funktionieren wird. Siehe dazu:

      FileReader.readAsBinaryString()

    Nach dem, was man so liest, ist die Methode 2012 vom W3C als veraltet eingestuft und aus der API Spezfikation entfernt worden. Warum die dann auf einmal in 2017 wieder in die Spezifikation reingekommen ist, kann ich nicht sagen. Sicherer würde es mir aber dennoch erscheinen, eine Methode zu verwenden, die nicht so einen Hickhack durchmachen musste.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Freitag, 13. April 2018 09:53
    Moderator
  • Hallo Stefan,
    ok, das mit readAsNiaryString() wusste ich nicht.
    Jetzt funktioniert es auch mit:
    var strBase64 = reader.result.slice(reader.result.lastIndexOf("base64,") + 7);
    Ich hoffe, das ist jetzt der richtige Weg.
    Danke nochmals für deine Hilfe.

    Viele Grüße, Volker

    Freitag, 13. April 2018 10:26
  • Hallo Volker,

    sollte passen. Ob Du das nun client- oder serverseitig machst, ist eigentlich egal. Serverseitig ist die Performance bei großen Dateien evtl. besser.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Freitag, 13. April 2018 10:40
    Moderator
  • Na dann werd ich das so machen.
    :)

    Ich stellte bereits Eingangs die Frage: Gibt es für größere Dateien (wie groß auch immer das sein mag) evtl. eine andere Methode, die vielleicht perfomanter ist?


    Viele Grüße, Volker

    Freitag, 13. April 2018 10:46
  • Noch der Vollständigkeit halber die fertigen Funktionen:

    Javascript:

            function fnUploadFile()
            {
                var file = document.getElementById('FileUpload').files[0];
                var reader = new FileReader();
                var fname = file.name;
                reader.readAsDataURL(file);
                reader.onload = function ()
                {
                    var strBase64 = reader.result;
                    var Url = "/Services/DateiService.svc/fnUploadFile";
                    var Data = '{ "strFileName": "' + fname + '", "strBase64": "' + strBase64 + '"}';
    
                    $.ajax({
                        type: Type,
                        url: Url,
                        data: Data,
                        cache: false,
                        async: false,
                        contentType: ContentType,
                        dataType: DataType,
                        processdata: ProcessData,
                        cache: false,
                        success: function (data)
                        {
                            if (data.d !== "OK")
                            {
                                //irgendwas
                            }
                        },
                        error: function (data)
                        {
                            alert("Fehler: " + data.status + ' - ' + data.statusText + '\n\nServermeldung:\n' + data.responseText);
                        }
                    });
    
                    //var responsedata = CallService(null, "nix");
                };
                reader.onerror = function (error)
                {
                    retValue = error;
                    console.log('Error: ', error);
                };
            }


    WebService:

    <ServiceContract(Namespace:="http://tempuri.org")>
    <AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)>
    Public Class DateiService
        Inherits System.Web.UI.Page
        <OperationContract()>
        <WebInvoke(Method:="POST", RequestFormat:=WebMessageFormat.Json, ResponseFormat:=WebMessageFormat.Json)>
        Public Function fnUploadFile(strBase64 As String, strFileName As String) As String
    
            Dim intStart As Integer = strBase64.LastIndexOf("base64,") + 7
            Dim intEnde As Integer = strBase64.Length - intStart
    
            strBase64 = strBase64.Substring(intStart, intEnde)
    
            Dim bytes() As Byte = Convert.FromBase64String(strBase64)
            Dim strPath As String = Server.MapPath("/Storage/" + strFileName)
    
            File.WriteAllBytes(strPath, bytes)
            Return "OK"
        End Function
    
    End Class
    Ggf. müssen je nach Dateigröße noch die Beschränkungen in den Bindings in der Web.config eingestellt werden, da sonst der Fehler 413: Request Entity Too Large auftritt:
        <bindings>
          <webHttpBinding>
            <binding maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" receiveTimeout="00:03:00"/>
          </webHttpBinding>
          <basicHttpBinding>
            <binding maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" receiveTimeout="00:03:00"/>
          </basicHttpBinding>
        </bindings>


    Viele Grüße, Volker




    • Bearbeitet Volker S Freitag, 13. April 2018 11:04
    Freitag, 13. April 2018 10:57