I am new to C# and I'm really having a trouble on finding a way to convert files(doc, xlsx, jpg, png, etc.) to base64.
So far, what I got is a way to retrieve the path using Directory.GetFiles()....but this is not the result I was expecting.
What I expected it to do is get the data of the files(not the path) and convert it to base64 so that I can display it on my front-end.
Any idea?
Try this:
foreach (string filePath in Directory.GetFiles(#"C:\directory"))
{
Byte[] bytes = File.ReadAllBytes(filePath);
String file = Convert.ToBase64String(bytes);
}
Related
I want to attach pdf from url into CRM "activitymimeattachment". Everything works fine but im getting empty pdf attachments (even the size is the same as original pdf). Could it be some problem with Encoding or converting? Maybe somebody could help me with this?
I see that email is created with attachment which is empty, but the size is the same as for original pdf.
Entity attachment = new Entity("activitymimeattachment");
attachment["subject"] = "Attachment";
string fileName = "Invoice.pdf";
attachment["filename"] = fileName;
WebClient wc = new WebClient();
string theTextFile = wc.DownloadString(url);
byte[] fileStream = Encoding.ASCII.GetBytes(theTextFile);
attachment["body"] = Convert.ToBase64String(fileStream);
attachment["mimetype"] = "application/pdf";
attachment["attachmentnumber"] = 1;
attachment["objectid"] = new EntityReference("email", emailguid);
attachment["objecttypecode"] = "email";
service.Create(attachment);
I believe the encoding is issue. The PDF is neither a string nor an ASCII file so these lines are at fault:
string theTextFile = wc.DownloadString(url);
byte[] fileStream = Encoding.ASCII.GetBytes(theTextFile);
I would suggest changing your web client to download a binary file i.e. application/pdf and save the file locally e.g to d:\temp\invoice.pdf.
Then you can do this:
var bytes = File.ReadAllBytes(#"d:\temp\invoice.pdf");
var body = Convert.ToBase64String(bytes);
In short, avoid trying to put the PDF into a string, or using the ASCII encoding to get its byte array. It's a binary file until you convert it to Base64.
Of course you can also probably get your web client to download the file into memory and convert it to Base64 without writing the file locally. I just wanted the simplest example to make the point about the encoding.
Thank You for advice #Aron. I actually have found a solution which is very simnply. I just used another method from WebClient class. The main thing I needed to change DownloadString(url) method into DownloadData(url) method:
WebClient wc = new WebClient();
byte[] theTextFile = wc.DownloadData(url);
attachment["body"] = Convert.ToBase64String(theTextFile);enter code here
If i read byte array from a file and write it using below code
byte[] bytes = File.ReadAllBytes(filePath);
File.WriteAllBytes(filePath, byteArr);
works perfectly fine.I can open and view the written file properly.
But if i read file contents into a string and then convert it to byte array using below function
string s = File.ReadAllText(filePath);
var byteArr = System.Text.Encoding.UTF8.GetBytes(s);
the size of byte array is more than the previous array read directly from file and the values are also different, hence if i write the file using this array the cannot be read when opened
Note:- File is utf-8 encoded
i found out that using below code
using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8, true))
{
reader.Peek(); // you need this!
var encoding = reader.CurrentEncoding;
}
Unable to understand why both the array differs??
I was using the below attached image for converting and then writing
With
using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8, true))
{
reader.Peek(); // you need this!
var encoding = reader.CurrentEncoding;
}
your var encoding will just echo the Encoding.UTF8 parameter. You are deceiving yourself there.
A binary file just has no text encoding.
Need to save a file may be anything an image or a text
Then just use ReadAllBytes/WriteAllBytes. A text file is always also a byte[], but not all file types are text. You would need Base64 encoding first and that just adds to the size.
The safest way to convert byte arrays to strings is indeed encoding it in something like base64.
Like:
string s= Convert.ToBase64String(bytes);
byte[] bytes = Convert.FromBase64String(s);
So I'm trying to come up with the code to convert a image to base64 version.
But I get a exception thrown.
System.IO.FileNotFoundException: 'C:\content\images\thumbs\0000001_camping_650.jpeg'
Now I'm working on a copy of the website on my local machine, but the images are stored on the test server. So I'm fairly sure this is where the problem is coming from.
Also the database is nots tored locally either, but on the sql server.
Both the sql server and test server are public facing.
This is the code I'm working with:
string base64String = string.Empty;
// Convert Image to Base64
using (var img = System.Drawing.Image.FromFile(Path.GetFullPath(pictureModel.ImageUrl))) // Image Path from File Upload Controller
{
using (var memStream = new MemoryStream())
{
img.Save(memStream, img.RawFormat);
byte[] imageBytes = memStream.ToArray();
// Convert byte[] to Base64 String
base64String = Convert.ToBase64String(imageBytes);
string ImageBase64 = base64String;
// return base64String;
}
}
Debugging output for this:
System.Diagnostics.Debug.WriteLine(pictureModel.ImageUrl);
System.Diagnostics.Debug.WriteLine(Path.GetFullPath(pictureModel.ImageUrl));
is this:
/content/images/thumbs/0000001_camping_650.jpeg
C:\content\images\thumbs\0000001_camping_650.jpeg
Not sure how to go about solving this one.
Im also working with a bit bucket repository, so the content\images\thumbs\ directory is excluded from the repository.
My solution on the local machine is C:\projects\test-website so I think I just need to figure out that path and is will work for the test and live site.
Cheers
Refactor your code as below:
string base64String = string.Empty;
// Convert Image to Base64
using (var img = System.Drawing.Image.FromFile(Server.MapPath("~") + pictureModel.ImageUrl))) // Image Path from File Upload Controller
{
using (var memStream = new MemoryStream())
{
img.Save(memStream, img.RawFormat);
byte[] imageBytes = memStream.ToArray();
// Convert byte[] to Base64 String
base64String = Convert.ToBase64String(imageBytes);
string ImageBase64 = base64String;
// return base64String;
}
}
Ok so looks like I figured it out.
First step was to copy all the images into the solution.
Then I needed to use the Server.MapPath to get the absolute path to the image.
using (var img = System.Drawing.Image.FromFile(Server.MapPath(pictureModel.ImageUrl))) // Image Path from File Upload Controller
{
using (var memStream = new MemoryStream())
{
img.Save(memStream, img.RawFormat);
byte[] imageBytes = memStream.ToArray();
// Convert byte[] to Base64 String
base64String = Convert.ToBase64String(imageBytes);
string ImageBase64 = base64String;
// return base64String;
}
}
So now when I do this output:
System.Diagnostics.Debug.WriteLine(Server.MapPath(pictureModel.ImageUrl));
I get this path:
C:\projects\test-website\Presentation\Nop.Web\content\images\thumbs\0000001_camping_650.jpeg
I think this will be correct so will accept my answer when I confirm it all works, got another error to figure out now :/
Sigh the joys of coding
If your local machine is not your server machine, you can try to show the path from server to your client machine.
Firstly, you need to share your root folder.
Then, access your shared folder with server's IP address. For example:
'\10.0.0.164\content\images\thumbs\0000001_camping_650.jpeg'
If you were testing on your local machine.
Kindly check if that file exist in your local machine
'C:\content\images\thumbs\0000001_camping_650.jpeg'
or check the location of your application where it is located.
I have a div with an image inside of it. In javascript I am getting the div, and sending the innerHTML of the div to the server. The javascript is oversimplified below:
function uploadImage() {
var imageInfo = document.getElementById('divImage').innerHTML;
PageMethods.uploadImage(imageInfo, onSuccess, onError);
} //end function
I am currently receiving this on the server as a string.
[WebMethod]
public static string uploadImage(string base64FileString){...}
The results are as follows:
<img height="150" width="150" title="name.png" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA...../>
I need to save this image to disk, and I'm at a loss. It's my understanding that I could get everything past the "base64," (using a split) and create an image using the following:
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(base64FileString);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
System.Drawing.Image image = System.Drawing.Image.FromStream(ms, true);
image.Save(.....);
But this seems very inefficient. Is there a better way to create the image from the string, a better way to receive the string, or better way to pass the string?
You can use File.WriteAllBytes:
byte[] imageBytes = Convert.FromBase64String(base64FileString);
File.WriteAllBytes(path, imageBytes);
Absolutely no need to go through MemoryStream and the System.Drawing namespace once you have the byte[].
I know there must be a better way to do this, but I have a solution that at least works. If anyone can point out a more sophisticated way I'm all ears. I would have assumed there was some sort of object that would receive the img on the server to save to disk, but maybe not.
Javascript and webmethod remain unchanged. I passed the InnerHTML of the div to the server, and accept it as a string. On the server I used multiple splits (which I understand to be very slow) to get at the base64 part of the image.
[WebMethod]
public static string uploadImage(string base64FileString){
//Get all of the text right of the comma
string base64PartTemp= base64FileString.Split(',')[1];
//The final part of the base64 had a \" to remove
//Now base64PartFinal is the base64 part of the image only
string base64PartFinal= base64PartTemp.Split('\"')[0];
//Get all of the text to the right of the period from original string
string fileTypePart = base64FileString.Split('.')[1];
//Because the file is an image the file type will be 3 chars
string fileType = fileTypePart.Substring(0, 3);
//Use a new guid for the file name, and append the fileType
string finalFileName = Guid.NewGuid() + "." + fileType;
//Turn the final base64 part into byte array
byte[] imageBytes = Convert.FromBase64String(base64PartFinal);
//Get the working directory of the project to store the files
string path= System.AppDomain.CurrentDomain.BaseDirectory.ToString();
//Append that I want to put the image in the images folder, under a designated filename
path += "Images/" + finalFileName;
//Write the image to file
File.WriteAllBytes(path, imageBytes);
...
}
I couldn't find an answer to this for a few days. I hope it helps someone. Like I said, may not be the most efficient solution, but it does work.
I have literally tried every possible way on this but apparently I just can't figure out the right one.
I am trying to upload images to the next-gen gallery that is installed on a wordpress blog. Everything about xml-rpc is working since I am able to do all other stuff with it.
The problem is that server returns an error saying the image is not a valid one. Which is quite obvious that the problem is about base64. However, for test purposes i copied and checked the base64 string and realized it is just right, it converts right to the image using an external base64 to image converter.
This is the line that submits the query.
result = categories.newImage(1, "admin", "password", newImage);
The struct for newImage is;
public struct imageI
{
public string name;
public string type;
public string bits;
public bool overwrite;
public int gallery;
public int image_id;
}
And this is how a new one is initialized, along with converting an image into base64
//Creating the image base64 string
string filename = "asd.jpg";
Image image1 = Image.FromFile(filename);
string base64 = ImageToBase64(image1, image1.RawFormat);
//for test purposes i copied and checked the base64 and it is just right, it converts right to the image using an external base64 to image converter.
Clipboard.SetText(base64);
//Creating a newImage
imageI newImage = default(imageI);
newImage.name = "newImage";
newImage.bits = base64;
newImage.gallery= 86;
And finally my method "ImageToBase64(Image, ImageFomat)";
public string ImageToBase64(Image image, System.Drawing.Imaging.ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}
In case anybody bumps on this, I figured it out, on the line;
newImage.name = "newImage"; the file name should be the same with the one you are uploading, or at least it should have the same extension so that the function in xml-rpc file can resolve the extension and check if it's okay to upload or not.