Converting file into Base64String and back again - c#

The title says it all:
I read in a tar.gz archive like so
break the file into an array of bytes
Convert those bytes into a Base64 string
Convert that Base64 string back into an array of bytes
Write those bytes back into a new tar.gz file
I can confirm that both files are the same size (the below method returns true) but I can no longer extract the copy version.
Am I missing something?
Boolean MyMethod(){
using (StreamReader sr = new StreamReader("C:\...\file.tar.gz")) {
String AsString = sr.ReadToEnd();
byte[] AsBytes = new byte[AsString.Length];
Buffer.BlockCopy(AsString.ToCharArray(), 0, AsBytes, 0, AsBytes.Length);
String AsBase64String = Convert.ToBase64String(AsBytes);
byte[] tempBytes = Convert.FromBase64String(AsBase64String);
File.WriteAllBytes(#"C:\...\file_copy.tar.gz", tempBytes);
}
FileInfo orig = new FileInfo("C:\...\file.tar.gz");
FileInfo copy = new FileInfo("C:\...\file_copy.tar.gz");
// Confirm that both original and copy file have the same number of bytes
return (orig.Length) == (copy.Length);
}
EDIT: The working example is much simpler (Thanks to #T.S.):
Boolean MyMethod(){
byte[] AsBytes = File.ReadAllBytes(#"C:\...\file.tar.gz");
String AsBase64String = Convert.ToBase64String(AsBytes);
byte[] tempBytes = Convert.FromBase64String(AsBase64String);
File.WriteAllBytes(#"C:\...\file_copy.tar.gz", tempBytes);
FileInfo orig = new FileInfo(#"C:\...\file.tar.gz");
FileInfo copy = new FileInfo(#"C:\...\file_copy.tar.gz");
// Confirm that both original and copy file have the same number of bytes
return (orig.Length) == (copy.Length);
}
Thanks!

If you want for some reason to convert your file to base-64 string. Like if you want to pass it via internet, etc... you can do this
Byte[] bytes = File.ReadAllBytes("path");
String file = Convert.ToBase64String(bytes);
And correspondingly, read back to file:
Byte[] bytes = Convert.FromBase64String(b64Str);
File.WriteAllBytes(path, bytes);

Another working example in VB.NET:
Public Function base64Encode(ByVal myDataToEncode As String) As String
Try
Dim myEncodeData_byte As Byte() = New Byte(myDataToEncode.Length - 1) {}
myEncodeData_byte = System.Text.Encoding.UTF8.GetBytes(myDataToEncode)
Dim myEncodedData As String = Convert.ToBase64String(myEncodeData_byte)
Return myEncodedData
Catch ex As Exception
Throw (New Exception("Error in base64Encode" & ex.Message))
End Try
'
End Function

private String encodeFileToBase64Binary(File file){
String encodedfile = null;
try {
FileInputStream fileInputStreamReader = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
fileInputStreamReader.read(bytes);
encodedfile = Base64.encodeBase64(bytes).toString();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encodedfile;
}

For Java, consider using Apache Commons FileUtils:
/**
* Convert a file to base64 string representation
*/
public String fileToBase64(File file) throws IOException {
final byte[] bytes = FileUtils.readFileToByteArray(file);
return Base64.getEncoder().encodeToString(bytes);
}
/**
* Convert base64 string representation to a file
*/
public void base64ToFile(String base64String, String filePath) throws IOException {
byte[] bytes = Base64.getDecoder().decode(base64String);
FileUtils.writeByteArrayToFile(new File(filePath), bytes);
}

Related

Process byte arrays correctly Encoding Utf-8 [duplicate]

This question already has an answer here:
FromBase64String/UTF Encoding
(1 answer)
Closed 2 years ago.
I am trying to download a PDF file and encode it in UTF-8 format and then transform it back into a Base64 to attach it to a MailMessage, however I get an exception when passing the string to Base64.
exception
The input is not a valid Base-64 string as it contains a non-base 64 character...
my code...
try
{
if (attachment.Uri.Contains("http") || attachment.Uri.Contains("https"))
{
byte[] contentByte = null;
using (var webClient = new WebClient())
{
webClient.UseDefaultCredentials = true;
Uri uri = new Uri(attachment.Uri);
contentByte = webClient.DownloadData(uri);
}
MemoryStream memStream = new MemoryStream(contentByte);
String fullString = Encoding.UTF8.GetString(memStream.ToArray());
String stringData = fullString.Split(',')[1];
byte[] byteData = System.Convert.FromBase64String(stringData);
MemoryStream streamData = new MemoryStream(byteData);
Attachment attachmentDoc = new Attachment(streamData, fileName);
mail.Attachments.Add(attachmentDoc);
}
}
catch (Exception ex)
{
notificationLog.Error.Write(String.Format("Sendmail error. Attachment not found: " + attachment.FileName));
}
You are going about this the wrong way.
You are trying to decode the PDF as UTF-8 (which it is not) to UTF-16, and then decode that UTF-16 as Base64 (which it is not) to a byte array, then attach those bytes to the email. That is the complete opposite of what you need.
Base64 operates on bytes, not strings/characters. There is no need to encode a PDF (a binary file) to UTF-8 before encoding it in Base64. Just encode the PDF bytes as-is straight to Base64, eg:
try
{
if (attachment.Uri.StartsWith("http:") || attachment.Uri.StartsWith("https:"))
{
byte[] contentByte = null;
using (var webClient = new WebClient())
{
webClient.UseDefaultCredentials = true;
Uri uri = new Uri(attachment.Uri);
contentByte = webClient.DownloadData(uri);
}
String stringData = System.Convert.ToBase64String(contentByte);
MemoryStream memStream = new MemoryStream(Encoding.ASCII.GetBytes(stringData));
Attachment attachmentDoc = new Attachment(memStream, fileName);
mail.Attachments.Add(attachmentDoc);
}
}
catch (Exception ex)
{
notificationLog.Error.Write(String.Format("Sendmail error. Attachment not found: " + attachment.FileName));
}
However, using this approach, the receiver won't be able to decode the PDF correctly, because it won't know the PDF bytes were encoded in Base64.
Fortunately, the Attachment class can handle the Base64 for you, and notify the receiver of the encoding. Just give the Attachment the raw PDF bytes as-is, and set its TransferEncoding property to Base64, eg:
try
{
if (attachment.Uri.StartsWith("http:") || attachment.Uri.StartsWith("https:"))
{
byte[] contentByte = null;
using (var webClient = new WebClient())
{
webClient.UseDefaultCredentials = true;
Uri uri = new Uri(attachment.Uri);
contentByte = webClient.DownloadData(uri);
}
MemoryStream memStream = new MemoryStream(contentByte);
Attachment attachmentDoc = new Attachment(memStream, fileName);
attachmentDoc.TransferEncoding = TransferEncoding.Base64;
mail.Attachments.Add(attachmentDoc);
}
}
catch (Exception ex)
{
notificationLog.Error.Write(String.Format("Sendmail error. Attachment not found: " + attachment.FileName));
}

Saving an image from bytes

I am trying to create an API which will save an image at a given location .
Below is my Code for that
Image image = Image.FromFile(#"C:\Users\abc\Desktop\img-logo.jpg");
byte[] bytes = (byte[])(new ImageConverter()).ConvertTo(image, typeof(byte[]));
string str = Convert.ToBase64String(bytes);
Save_Application_Image("12004", str);
and the method in API
public void Save_Application_Image(string staffCode , string bytearray)
{
try
{
byte[] bytes = Convert.FromBase64String(bytearray);
file_path = "~/uploads/" + file_name;
FileStream file = File.Create(HttpContext.Current.Server.MapPath(file_path));
file.Write(bytes, 0, bytes.Length);
file.Close();
}
catch(Exception ex)
{
logger.LogError(ex);
}
finally
{
}
}
This api has to be called from Android Application so I will receive two string parameter.
It is saving the file perfectly but file is not readable. No preview for image file.
What is the right approach for this ?
I'm unsure of how the ImageConverter works, but I've used this before to convert Images to byte[]:
Image image = Image.FromFile(#"C:\Users\abc\Desktop\img-logo.jpg");
using (var stream = new MemoryStream())
{
image.Save(stream);
string savedImage = Convert.ToBase64String(stream.ToArray());
Save_Application_Image("12004", str);
}

Converting byte array to image

We are using Flash to send an image to the servers and upload an image. The way we're trying to do this is by sending the bytes to the server through a parameter and then converting the bytes to an image.
http://i.gyazo.com/fb8225af80ef465b0262d97f63bd54b2.png
In the image the object is sending a few different bits of information. I'm not sure if I am supposed to just receive one bit of information instead of the entire object.
So far I have the post request
string byteArray = Request["bytes"];
Then I am trying to convert it to an image
string file_name = Guid.NewGuid().ToString();
//byte[] imageBytes = Convert.FromBase64String(byteArray);
Derio.App.Model.Helper.ByteArrayToFile(file_name, Derio.App.Model.Helper.GetBytes(byteArray));
My helper method looks like -
public static class Helper
{
public static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
public static string ByteArrayToFile(string _FileName, byte[] _ByteArray)
{
try
{
// Open file for reading
System.IO.FileStream _FileStream =
new System.IO.FileStream(_FileName, System.IO.FileMode.Create,
System.IO.FileAccess.Write);
// Writes a block of bytes to this stream using data from
// a byte array.
_FileStream.Write(_ByteArray, 0, _ByteArray.Length);
// close file stream
_FileStream.Close();
return "true";
}
catch (Exception _Exception)
{
// Error
return "Exception caught in process:" + _Exception.ToString();
}
}
}
We've multiple different methods such as trying to convert it from Base64String to an image.
I can't for the life of me though figure out what I am doing wrong.
What happens when you try this:
string file_name = Guid.NewGuid().ToString();
string byteArray = Request["bytes"];
byte[] imageBytes = Convert.FromBase64String(byteArray);
IO.File.WriteAllBytes(file_name, imageBytes);

Help me, throwing exception error in decoding code. help needed

To encode a string
Code:
public string base64Encode(string data)
{
try
{
byte[] encData_byte = new byte[data.Length];
encData_byte = System.Text.Encoding.UTF8.GetBytes(data);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
catch(Exception e)
{
throw new Exception("Error in base64Encode" + e.Message);
}
}
and to decode
Code:
public string base64Decode(string data)
{
try
{
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(data);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
string result = new String(decoded_char);
return result;
}
catch(Exception e)
{
throw new Exception("Error in base64Decode" + e.Message);
}
}
You haven't said what error you're getting, but surely your second code should simply be:
return Encoding.UTF8.GetString(Convert.FromBase64String(data));
You don't need to create a new UTF8Encoding
You don't need to worry about decoders explicitly
Additionally, your exception handling is nasty - the stack trace would already show where the error occurs, but by catching it and rethrowing just Exception you're hiding the original exception type. Just remove the try/catch blocks from both your methods. (And rename them to match .NET naming conventions.)
Basically, your code can look as simple as this:
public static string Base64AndUtf8Encode(string text)
{
return Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
}
public static string Base64AndUtf8Decode(string base64)
{
return Encoding.UTF8.GetString(Convert.FromBase64String(base64));
}
Obviously you can split it into separate statements if you want, but it can stil be pretty short:
public static string Base64AndUtf8Encode(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
return Convert.ToBase64String(bytes);
}
public static string Base64AndUtf8Decode(string base64)
{
bytes[] bytes = Convert.FromBase64String(base64);
return Encoding.UTF8.GetString(bytes);
}

how to send binary data within an xml string

I want to send a binary file to .net c# component in the following xml format
<BinaryFileString fileType='pdf'>
<!--binary file data string here-->
</BinaryFileString>
In the called component I will use the above xml string and convert the binary string received within the BinaryFileString tag, into a file as specified by the filetype='' attribute. The file type could be doc/pdf/xls/rtf
I have the code in the calling application to get out the bytes from the file to be sent. How do I prepare it to be sent with xml tags wrapped around it? I want the application to send out a string to the component and not a byte stream. This is because there is no way I can decipher the file type [pdf/doc/xls] just by looking at the byte stream. Hence the xml string with the filetype attribute. Any ideas on this?
method for extracting Bytes below
FileStream fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
using (Stream input = fs)
{
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{}
}
return buffer;
Thanks.
Edit:
Just to clarify why I am using an xml string rather than setting properties on my component. Actually my calling app is trying to simulate how Siebel will call my component.
http://download.oracle.com/docs/cd/E05553_01/books/eScript/eScript_JSReference244.html#wp1014380
Im not sure if Siebel can set my components properties as I need it to. So Im working on the angle of it sending the data in xml.
Base64 representation is universaly used to represent binary data.
public void EncodeWithString() {
System.IO.FileStream inFile;
byte[] binaryData;
try {
inFile = new System.IO.FileStream(inputFileName,
System.IO.FileMode.Open,
System.IO.FileAccess.Read);
binaryData = new Byte[inFile.Length];
long bytesRead = inFile.Read(binaryData, 0,
(int)inFile.Length);
inFile.Close();
}
catch (System.Exception exp) {
// Error creating stream or reading from it.
System.Console.WriteLine("{0}", exp.Message);
return;
}
// Convert the binary input into Base64 UUEncoded output.
string base64String;
try {
base64String =
System.Convert.ToBase64String(binaryData,
0,
binaryData.Length);
}
catch (System.ArgumentNullException) {
System.Console.WriteLine("Binary data array is null.");
return;
}
// Write the UUEncoded version to the XML file.
System.IO.StreamWriter outFile;
try {
outFile = new System.IO.StreamWriter(outputFileName,
false,
System.Text.Encoding.ASCII);
outFile.Write("<BinaryFileString fileType='pdf'>");
outFile.Write(base64String);
outFile.Write("</BinaryFileString>");
outFile.Close();
}
catch (System.Exception exp) {
// Error creating stream or writing to it.
System.Console.WriteLine("{0}", exp.Message);
}
}
At the receiving end you can reverse this and get back original file content as mentioned below.
// Convert the Base64 UUEncoded input into binary output.
byte[] binaryData;
try {
binaryData =
System.Convert.FromBase64String(base64String);
}
catch (System.ArgumentNullException) {
System.Console.WriteLine("Base 64 string is null.");
return;
}
catch (System.FormatException) {
System.Console.WriteLine("Base 64 string length is not " +
"4 or is not an even multiple of 4." );
return;
}
Can you BASE64 your bytes? MSDN ref: Convert.ToBase64, Convert.FromBase64String
expanding on #russau's answer it will work like this:
var s = "Hello World";
var b = Encoding.Default.GetBytes(s);
var bstr = Convert.ToBase64String(b);
Console.WriteLine("Original String:" + s);
Console.WriteLine("Base64 String:" + bstr);
var fromBStr = Convert.FromBase64String(bstr);
var st = Encoding.Default.GetString(fromBStr);
Console.WriteLine("Converted string: " + st);
you wont need first two lines:
var s = "Hello World";
var b = Encoding.Default.GetBytes(s);
as you already have a byte array. I've used string to show that you get exactly the same value you started with in the end when you convert byte array from Convert.FromBase64String
You mention that you are calling a C# component. I'm not sure I understand why using this component means you need to create an XML string.
Is it possible to define classes to hold your data instead of using an XML string? e.g.
public enum FileType
{
Word,
Excel,
RichText,
PDF
}
public class FileData
{
public FileType TypeOfFile
{
get;
set;
}
public byte[] Data
{
get;
set;
}
}
Then the caller of the component just sets the FileType and the byte[]. The component's interface would then be more explicitly defined (FileData class as opposed to the more generic string or XmlDocument).

Categories

Resources