2009-01-24 14 views
26

Kann jemand etwas Licht zur Verfügung stellen, wie man das macht? Ich kann dies für normalen Text oder Byte-Array tun, aber nicht sicher, wie man sich für ein PDF nähert. stopf ich die pdf zuerst in ein Byte-Array?Base64 Codieren Sie ein PDF in C#?

+2

Warum sollte ein PDF anders als ein Byte-Array sein? –

Antwort

39

Verwenden Sie File.ReadAllBytes, um die PDF-Datei zu laden, und codieren Sie dann das Byte-Array unter Verwendung von Convert.ToBase64String(bytes) als normal.

+2

Huch! Das könnte groß werden. –

+0

In der Tat. Aber heutzutage haben Maschinen viel Speicher. Und wenn nötig, ist das Lesen von gepufferten Blöcken aus einer Datei eine ziemlich Standardtechnik :) –

+0

Funktioniert gut für das, was ich im Moment brauche. Danke für den Tipp! – Tone

34

Es gibt eine Möglichkeit, dies in Blöcken zu tun, so dass Sie nicht eine Tonne Speicher auf einmal brennen müssen.

.Net enthält einen Encoder, der das Chunking ausführen kann, aber es ist irgendwie ein seltsamer Ort. Sie legen es in den Namespace System.Security.Cryptography.

Ich habe den folgenden Beispielcode getestet, und ich bekomme identische Ausgabe entweder mit meiner Methode oder Andrews Methode oben.

So funktioniert es: Sie starten eine Klasse namens CryptoStream. Dies ist eine Art Adapter, der in einen anderen Stream gesteckt wird. Sie verbinden eine Klasse namens CryptoTransform mit dem CryptoStream (der wiederum an Ihren Datei-/Speicher-/Netzwerkstream angehängt ist) und führt Datentransformationen an den Daten durch, während sie vom Stream gelesen oder in den Stream geschrieben werden.

Normalerweise ist die Umwandlung Verschlüsselung/Entschlüsselung, aber .net enthält auch ToBase64 und FromBase64 Transformationen, so dass wir nicht verschlüsseln werden, nur Codierung.

Hier ist der Code. Ich habe eine (vielleicht schlecht benannte) Implementierung von Andrews Vorschlag eingefügt, damit Sie die Ausgabe vergleichen können.

 

    class Base64Encoder 
    { 
     public void Encode(string inFileName, string outFileName) 
     { 
      System.Security.Cryptography.ICryptoTransform transform = new System.Security.Cryptography.ToBase64Transform(); 
      using(System.IO.FileStream inFile = System.IO.File.OpenRead(inFileName), 
             outFile = System.IO.File.Create(outFileName)) 
      using (System.Security.Cryptography.CryptoStream cryptStream = new System.Security.Cryptography.CryptoStream(outFile, transform, System.Security.Cryptography.CryptoStreamMode.Write)) 
      { 
       // I'm going to use a 4k buffer, tune this as needed 
       byte[] buffer = new byte[4096]; 
       int bytesRead; 

       while ((bytesRead = inFile.Read(buffer, 0, buffer.Length)) > 0) 
        cryptStream.Write(buffer, 0, bytesRead); 

       cryptStream.FlushFinalBlock(); 
      } 
     } 

     public void Decode(string inFileName, string outFileName) 
     { 
      System.Security.Cryptography.ICryptoTransform transform = new System.Security.Cryptography.FromBase64Transform(); 
      using (System.IO.FileStream inFile = System.IO.File.OpenRead(inFileName), 
             outFile = System.IO.File.Create(outFileName)) 
      using (System.Security.Cryptography.CryptoStream cryptStream = new System.Security.Cryptography.CryptoStream(inFile, transform, System.Security.Cryptography.CryptoStreamMode.Read)) 
      { 
       byte[] buffer = new byte[4096]; 
       int bytesRead; 

       while ((bytesRead = cryptStream.Read(buffer, 0, buffer.Length)) > 0) 
        outFile.Write(buffer, 0, bytesRead); 

       outFile.Flush(); 
      } 
     } 

     // this version of Encode pulls everything into memory at once 
     // you can compare the output of my Encode method above to the output of this one 
     // the output should be identical, but the crytostream version 
     // will use way less memory on a large file than this version. 
     public void MemoryEncode(string inFileName, string outFileName) 
     { 
      byte[] bytes = System.IO.File.ReadAllBytes(inFileName); 
      System.IO.File.WriteAllText(outFileName, System.Convert.ToBase64String(bytes)); 
     } 
    } 
 

Ich spiele auch mit, wo ich den CryptoStream anschließe. In der Encode-Methode, ich füge es an die Ausgabe (Schreiben) Strom, so wenn ich die CryptoStream Instanz, verwende ich seine Write() -Methode.

Wenn ich lese, bin ich es an den Eingang (Lesen) Strom anfügen, so verwende ich die Lese-Methode auf dem CryptoStream. Es spielt keine Rolle, an welchen Stream ich es anschließe. Ich muss nur das entsprechende Lese- oder Schreib-Enumerationselement an den CryptoStream-Konstruktor übergeben.

+0

Ich bin nicht gelaufen und habe das verifiziert, aber das sieht vielversprechend gut aus. Tolle Idee! +1 – codingbear

+1

Ich habe das getestet. Klappt wunderbar. Schön gemacht. – mcNux

+0

@mcNux: Danke! – JMarsch

Verwandte Themen