Post image from Windows Phone Application to PHP - c#

I am trying to develop an application for Windows Phone 7 which uploads a selected picture (from the picture chooser task) to a server with the use of PHP.
I am trying to use HttpWebRequest in order to do this. And the data is posted successfully too.
The Problem that I am facing is that the image is required to be encoded to base64 before posting.
And, I am not able to encode it properly.
This is my C# code so far:
public partial class SamplePage : PhoneApplicationPage
{
public SamplePage()
{
InitializeComponent();
}
PhotoChooserTask selectphoto = null;
private void SampleBtn_Click(object sender, RoutedEventArgs e)
{
selectphoto = new PhotoChooserTask();
selectphoto.Completed += new EventHandler<PhotoResult>(selectphoto_Completed);
selectphoto.Show();
}
void selectphoto_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
BinaryReader reader = new BinaryReader(e.ChosenPhoto);
image1.Source = new BitmapImage(new Uri(e.OriginalFileName));
txtBX.Text = e.OriginalFileName;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://"+QR_Reader.MainPage.txtBlck+"/beamer/saveimage.php");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
string str = BitmapToByte(image1);
MessageBox.Show(str);
string postData = String.Format("image={0}", str);
// Getting the request stream.
request.BeginGetRequestStream
(result =>
{
// Sending the request.
using (var requestStream = request.EndGetRequestStream(result))
{
using (StreamWriter writer = new StreamWriter(requestStream))
{
writer.Write(postData);
writer.Flush();
}
}
// Getting the response.
request.BeginGetResponse(responseResult =>
{
var webResponse = request.EndGetResponse(responseResult);
using (var responseStream = webResponse.GetResponseStream())
{
using (var streamReader = new StreamReader(responseStream))
{
string srresult = streamReader.ReadToEnd();
}
}
}, null);
}, null);
} // end of taskresult == OK
} // end of select photo completed
private Stream ImageToStream(Image image1)
{
WriteableBitmap wb = new WriteableBitmap(400, 400);
wb.Render(image1, new TranslateTransform { X = 400, Y = 400 });
wb.Invalidate();
Stream myStream = new MemoryStream();
wb.SaveJpeg(myStream, 400, 400, 0, 70);
return myStream;
}
private string BitmapToByte(Image image) //I suspect there is something wrong here
{
Stream photoStream = ImageToStream(image);
BitmapImage bimg = new BitmapImage();
bimg.SetSource(photoStream); //photoStream is a stream containing data for a photo
byte[] bytearray = null;
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap wbitmp = new WriteableBitmap(bimg);
wbitmp.SaveJpeg(ms, wbitmp.PixelWidth, wbitmp.PixelHeight, 0, 100);
bytearray = ms.ToArray();
}
string str = Convert.ToBase64String(bytearray);
return str;
}
}
The BitmapToByte function is used to convert the image to base64 string.
And, the ImageToStream function is used to convert it to stream.
Now, I seriously suspect that there is something wrong in these two functions.
Further, I'm getting exactly the same base64 string for every image. Yes, I'm getting exactly same base64 string irrespective of what image I'm selecting. This is very weird.
I don't know what is wrong with this.
I've uploaded a text file here: http://textuploader.com/?p=6&id=vWZy
It contains that base64 string.
On, the server side, the PHP is accepting the postdata successfully and the decoding is working perfectly too (I decoded some base64 strings manually to ensure this).
Only problem I'm facing is base64 encoding.
Please help me.
EDIT
I've made the following changes in the ImageToStream and BitmapToByte functions:
private MemoryStream ImageToStream(Image image1)
{
WriteableBitmap wb = new WriteableBitmap(400, 400);
wb.Render(image1, new TranslateTransform { X = 400, Y = 400 });
wb.Invalidate();
MemoryStream myStream = new MemoryStream();
wb.SaveJpeg(myStream, 400, 400, 0, 70);
return myStream;
}
private string BitmapToByte(Image image)
{
MemoryStream photoStream = ImageToStream(image);
byte[] bytearray = photoStream.ToArray();
string str = Convert.ToBase64String(bytearray);
return str;
}

You BitmapToByte method is tremendously overcomplicated. Change ImageToStream to return a MemoryStream and:
private string BitmapToByte(Image image)
{
MemoryStream photoStream = ImageToStream(image);
byte[] bytearray = photoStream.ToArray();
string str = Convert.ToBase64String(bytearray);
return str;
}

Related

sending binary file byte array to web api method

I have a requirement to post binary file of size 100MB data in the format of either JSON or byte array to Web API 1.1.
My client application is C# winforms application with x32 bit architecture. Where as I want to perform reading binary file from this client application and send this binary file byte array to Web API.
Current implementation in my winforms application is as below
var sFile = #"C"\binary.zip";
var mybytearray = File.ReadAllBytes(sFile);
var webRequest =
(HttpWebRequest)WebRequest.Create("http://localhost/filewriter");
webRequest.ContentType = "text/plain";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.AllowWriteStreamBuffering = true;
webRequest.Timeout = 100000;
webRequest.Headers.Add("fileName", Path.GetFileName(sFile));
webRequest.ContentLength = mybytearray.Length;
using (var dataStream = new StreamWriter(webRequest.GetRequestStream()))
dataStream.Write(mybytearray);
using (var response = webRequest.GetResponse())
{
if(response.StatusCode = HttpStatusCode.Ok;
return true;
}
below is written at my Web api method
[HttpPost]
public HttpResponseMessage filewriter(byte[] binaryData)
{
using (FileStream binaryFileStream = new FileStream("C:\\myNewFile.zip", FileMode.Create, FileAccess.ReadWrite))
{
binaryFileStream.Write(binaryData, 0, binaryData.Length);
}
}
As you can see, in above code I was not able to send byte array to web api method filewriter. Am I missing something that should work in this case.
Other way as I said I was tried same but instead of byte array with Json one as below
var sFile = #"C"\binary.zip";
var mybytearray = File.ReadAllBytes(sFile);
var mymodel = new model
{
fileName = sFile,
binaryData = mybytearray
};
var jsonResendObjects = JsonConvert.SerializeObject(mymodel);
var webRequest = (HttpWebRequest)WebRequest.Create("http://localhost/filewriter");
webRequest.ContentType = "application/json";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.AllowWriteStreamBuffering = true;
webRequest.Timeout = 100000;
webRequest.Headers.Add("fileName", Path.GetFileName(sFile));
webRequest.ContentLength = jsonResendObjects.Length;
byte[] responseData = null;
webRequest.AllowWriteStreamBuffering = true;
using (var dataStream = new StreamWriter(webRequest.GetRequestStream()))
dataStream.Write(jsonResendObjects);
On web api side
[HttpPost]
public HttpResponseMessage filewriter([FromBody]model mymodel)
{
using (FileStream binaryFileStream = new FileStream("C:\\myNewFile.zip", FileMode.Create, FileAccess.ReadWrite))
{
binaryFileStream.Write(mymodel.binarydata, 0, binaryDatabinarydat.Length);
}
}
According to me, it would be easy to use base64 encoding for
communication.
If you want to do so
First, convert your file to byte[] and then to base64 string
Like this:
byte[] bytes = File.ReadAllBytes("path");
string file = Convert.ToBase64String(bytes);
// You have base64 Data in "file" variable
On your WebAPI Endpoint accept string
[HttpPost]
public HttpResponseMessage filewriter(string fileData)
{
}
Then convert your base64 string back to byte[] and write it to file or whatever you want to do with that.
Like This:
// put your base64 string in b64str
Byte[] bytes = Convert.FromBase64String(b64Str);
File.WriteAllBytes(path, bytes);
And you can Compress your string Using GZIP Like this
public static void CopyTo(Stream src, Stream dest) {
byte[] bytes = new byte[4096];
int cnt;
while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) {
dest.Write(bytes, 0, cnt);
}
}
public static byte[] Zip(string str) {
var bytes = Encoding.UTF8.GetBytes(str);
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream()) {
using (var gs = new GZipStream(mso, CompressionMode.Compress)) {
//msi.CopyTo(gs);
CopyTo(msi, gs);
}
return mso.ToArray();
}
}
public static string Unzip(byte[] bytes) {
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream()) {
using (var gs = new GZipStream(msi, CompressionMode.Decompress)) {
//gs.CopyTo(mso);
CopyTo(gs, mso);
}
return Encoding.UTF8.GetString(mso.ToArray());
}
}
Reference:-
Convert file to base64 and back
GZip Compression

Load an image from URL as base64 string

I am trying to load an image as a base 64 string so that i can show it in a html like this:
<html><body><img src="data:image/jpeg;base64,/></img></body></html>
Heres my code so far, but it does not really work:
public async static Task<string> getImage(string url)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.Accept = "data:image/jpg;charset=base64";
request.Credentials = new NetworkCredential(user, pw);
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
StreamReader sr = new StreamReader(response.GetResponseStream());
return sr.ReadToEnd();
}
I tried using this method i found elsewhere to encode the return-String as base64, but when placing it in a html the image just shows the typical placeholder.
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
EDIT:
Here is how the html looks:
It seems to me that you need to separate the base64 part, which is only needed in your HTML, from fetching the data from the response. Just fetch the data from the URL as binary data and convert that to base64. Using HttpClient makes this simple:
public async static Task<string> GetImageAsBase64Url(string url)
{
var credentials = new NetworkCredential(user, pw);
using (var handler = new HttpClientHandler { Credentials = credentials })
using (var client = new HttpClient(handler))
{
var bytes = await client.GetByteArrayAsync(url);
return "image/jpeg;base64," + Convert.ToBase64String(bytes);
}
}
This assumes the image always will be a JPEG. If it could sometimes be a different content type, you may well want to fetch the response as an HttpResponse and use that to propagate the content type.
I suspect you may want to add caching here as well :)
using (HttpClient client = new HttpClient())
{
try
{
using (Stream stream = await client.GetStreamAsync(uri))
{
if (stream == null)
return (Picture)null;
byte[] buffer = new byte[16384];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int num = await stream.ReadAsync(buffer, 0, buffer.Length, cancellation);
int read;
if ((read = num) > 0)
ms.Write(buffer, 0, read);
else
break;
}
imageData = Convert.ToBase64String(ms.ToArray());
}
buffer = (byte[])null;
}
}
catch (Exception ex)
{
}
}
You must first get the image from disk, then convert it to byte[] and then again to base64.
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;
}
}

Retrieving favicon as icon instead of image

I used the favicon-code I found here to retrieve the favicon of the site loaded in the browser element.
I want to use this favicon as the icon of my Windows Form.
Thanks to JP Hellemons this code works:
private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
this.Icon = favicon(GetActiveBrowser().Url);
}
private WebBrowser GetActiveBrowser() {
return (WebBrowser)tabs.SelectedTab.Controls[0];
}
private Icon favicon(Uri url) {
WebRequest request = (HttpWebRequest)WebRequest.Create("http://" + url.Host + "/favicon.ico");
Bitmap bm = new Bitmap(32, 32);
MemoryStream memStream;
using (Stream response = request.GetResponse().GetResponseStream()) {
memStream = new MemoryStream();
byte[] buffer = new byte[1024];
int byteCount;
do {
byteCount = response.Read(buffer, 0, buffer.Length);
memStream.Write(buffer, 0, byteCount);
} while (byteCount > 0);
}
bm = new Bitmap(Image.FromStream(memStream));
if (bm != null) {
Icon ic = Icon.FromHandle(bm.GetHicon());
return ic;
} else
return Properties.Resources.GZbrowser;
}
According to this documentation, it should work from stream.
http://msdn.microsoft.com/en-us/library/system.drawing.icon.aspx
I used this article: http://odetocode.com/Blogs/scott/archive/2004/10/05/webrequest-and-binary-data.aspx
WebRequest request = (HttpWebRequest)WebRequest.Create("http://" + url.Host + "/favicon.ico");
Icon ic = new Icon(); // put default here
Bitmap bm = new Bitmap();
try
{
using(WebResponse response = request.GetResponse())
{
using(Stream responseStream = response.GetResponseStream())
{
using(MemoryStream ms = new MemoryStream())
{
var tmp = Image.FromStream(ms); // changed bitmap to image
bm = new Bitmap(tmp);
}
}
}
}catch{}
if(bm != null)
{
ic = Icon.FromHandle(bm.GetHicon);
}
return ic;
Edit: something like this should do it
Edit2: changed some things in the answer. Can you try this?
Final edit: (lol)
Just tested this in a windows form app and this works! :)
Uri url = new Uri("http://www.google.nl");
WebRequest request = (HttpWebRequest)WebRequest.Create("http://" + url.Host + "/favicon.ico");
Bitmap bm = new Bitmap(32,32);
MemoryStream memStream;
using (Stream response = request.GetResponse().GetResponseStream())
{
memStream = new MemoryStream();
byte[] buffer = new byte[1024];
int byteCount;
do
{
byteCount = response.Read(buffer, 0, buffer.Length);
memStream.Write(buffer, 0, byteCount);
} while (byteCount > 0);
}
bm = new Bitmap(Image.FromStream(memStream));
if (bm != null)
{
Icon ic = Icon.FromHandle(bm.GetHicon());
this.Icon = ic;
}
Read response byte array first, than create MemoryStream of it and create icon from that MemoryStream.
Network stream do not support seek operations that seem to be necessary for creating an icon.

converting a base 64 string to an image and saving it

Here is my code:
protected void SaveMyImage_Click(object sender, EventArgs e)
{
string imageUrl = Hidden1.Value;
string saveLocation = Server.MapPath("~/PictureUploads/whatever2.png") ;
HttpWebRequest imageRequest = (HttpWebRequest)WebRequest.Create(imageUrl);
WebResponse imageResponse = imageRequest.GetResponse();
Stream responseStream = imageResponse.GetResponseStream();
using (BinaryReader br = new BinaryReader(responseStream))
{
imageBytes = br.ReadBytes(500000);
br.Close();
}
responseStream.Close();
imageResponse.Close();
FileStream fs = new FileStream(saveLocation, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
try
{
bw.Write(imageBytes);
}
finally
{
fs.Close();
bw.Close();
}
}
}
The top imageUrl declartion is taking in a Base64 image string, and I want to convert it into an image. I think my set of code only works for images like "www.mysite.com/test.jpg" not for a Base64 string. Anybody have some suggestions? Thanks!
Here is an example, you can modify the method to accept a string parameter. Then just save the image object with image.Save(...).
public Image LoadImage()
{
//data:image/gif;base64,
//this image is a single pixel (black)
byte[] bytes = Convert.FromBase64String("R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==");
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
return image;
}
It is possible to get an exception A generic error occurred in GDI+. when the bytes represent a bitmap. If this is happening save the image before disposing the memory stream (while still inside the using statement).
You can save Base64 directly into file:
string filePath = "MyImage.jpg";
File.WriteAllBytes(filePath, Convert.FromBase64String(base64imageString));
Here is what I ended up going with.
private void SaveByteArrayAsImage(string fullOutputPath, string base64String)
{
byte[] bytes = Convert.FromBase64String(base64String);
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
image.Save(fullOutputPath, System.Drawing.Imaging.ImageFormat.Png);
}
I would suggest via Bitmap:
public void SaveImage(string base64)
{
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(base64)))
{
using (Bitmap bm2 = new Bitmap(ms))
{
bm2.Save("SavingPath" + "ImageName.jpg");
}
}
}
Here is working code for converting an image from a base64 string to an Image object and storing it in a folder with unique file name:
public void SaveImage()
{
string strm = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
//this is a simple white background image
var myfilename= string.Format(#"{0}", Guid.NewGuid());
//Generate unique filename
string filepath= "~/UserImages/" + myfilename+ ".jpeg";
var bytess = Convert.FromBase64String(strm);
using (var imageFile = new FileStream(filepath, FileMode.Create))
{
imageFile.Write(bytess, 0, bytess.Length);
imageFile.Flush();
}
}
In my case it works only with two line of code. Test the below C# code:
String dirPath = "C:\myfolder\";
String imgName = "my_mage_name.bmp";
byte[] imgByteArray = Convert.FromBase64String("your_base64_string");
File.WriteAllBytes(dirPath + imgName, imgByteArray);
That's it. Kindly up vote if you really find this solution works for you. Thanks in advance.
In a similar scenario what worked for me was the following:
byte[] bytes = Convert.FromBase64String(Base64String);
ImageTagId.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(bytes);
ImageTagId is the ID of the ASP image tag.
If you have a string of binary data which is Base64 encoded, you should be able to do the following:
byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
You should be able to write the resulting array to a file.
public bool SaveBase64(string Dir, string FileName, string FileType, string Base64ImageString)
{
try
{
string folder = System.Web.HttpContext.Current.Server.MapPath("~/") + Dir;
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
string filePath = folder + "/" + FileName + "." + FileType;
File.WriteAllBytes(filePath, Convert.FromBase64String(Base64ImageString));
return true;
}
catch
{
return false;
}
}
Using MemoryStream is not a good idea and violates a specification in MSDN for Image.FromStream(), where it says
You must keep the stream open for the lifetime of the Image.
A better solution is using ImageConverter, e.g:
public Image ConvertBase64ToImage(string base64)
=> (Bitmap)new ImageConverter().ConvertFrom(Convert.FromBase64String(base64));
In NetCore 6.0, you can use HttpClient and the async methods in the new File class.
The implementation is very simple:
static async Task DownloadFile(string imageUrl, string pathToSave)
{
var content = await GetUrlContent(url);
if (content != null)
{
await File.WriteAllBytesAsync(pathToSave, content);
}
}
static async Task<byte[]?> GetUrlContent(string url)
{
using (var client = new HttpClient())
using (var result = await client.GetAsync(url))
return result.IsSuccessStatusCode ? await result.Content.ReadAsByteArrayAsync():null;
}
Usage:
await DownloadFile("https://example.com/image.jpg", #"c:\temp\image.jpg");

How to use httpwebrequest to pull image from website to local file

I'm trying to use a local c# app to pull some images off a website to files on my local machine. I'm using the code listed below. I've tried both ASCII encoding and UTF8 encoding but the final file is not an correct. Does anyone see what I'm doing wrong? The url is active and correct and show the image just fine when I put the address in my browser.
private void button1_Click(object sender, EventArgs e)
{
HttpWebRequest lxRequest = (HttpWebRequest)WebRequest.Create("http://www.productimageswebsite.com/images/stock_jpgs/34891.jpg");
// returned values are returned as a stream, then read into a string
String lsResponse = string.Empty;
HttpWebResponse lxResponse = (HttpWebResponse)lxRequest.GetResponse();
using (StreamReader lxResponseStream = new StreamReader(lxResponse.GetResponseStream()))
{
lsResponse = lxResponseStream.ReadToEnd();
lxResponseStream.Close();
}
byte[] lnByte = System.Text.UTF8Encoding.UTF8.GetBytes(lsResponse);
System.IO.FileStream lxFS = new FileStream("34891.jpg", FileMode.Create);
lxFS.Write(lnByte, 0, lnByte.Length);
lxFS.Close();
MessageBox.Show("done");
}
nice image :D
try using the following code:
you needed to use a BinaryReader, 'cause an image file is binary data and thus not encoded in UTF or ASCII
edit: using'ified
HttpWebRequest lxRequest = (HttpWebRequest)WebRequest.Create(
"http://www.productimageswebsite.com/images/stock_jpgs/34891.jpg");
// returned values are returned as a stream, then read into a string
String lsResponse = string.Empty;
using (HttpWebResponse lxResponse = (HttpWebResponse)lxRequest.GetResponse()){
using (BinaryReader reader = new BinaryReader(lxResponse.GetResponseStream())) {
Byte[] lnByte = reader.ReadBytes(1 * 1024 * 1024 * 10);
using (FileStream lxFS = new FileStream("34891.jpg", FileMode.Create)) {
lxFS.Write(lnByte, 0, lnByte.Length);
}
}
}
MessageBox.Show("done");
Okay, here's the final answer. It uses a memorystream as a way to buffer the data from the reaponsestream.
private void button1_Click(object sender, EventArgs e)
{
byte[] lnBuffer;
byte[] lnFile;
HttpWebRequest lxRequest = (HttpWebRequest)WebRequest.Create("http://www.productimageswebsite.com/images/stock_jpgs/34891.jpg");
using (HttpWebResponse lxResponse = (HttpWebResponse)lxRequest.GetResponse())
{
using (BinaryReader lxBR = new BinaryReader(lxResponse.GetResponseStream()))
{
using (MemoryStream lxMS = new MemoryStream())
{
lnBuffer = lxBR.ReadBytes(1024);
while (lnBuffer.Length > 0)
{
lxMS.Write(lnBuffer, 0, lnBuffer.Length);
lnBuffer = lxBR.ReadBytes(1024);
}
lnFile = new byte[(int)lxMS.Length];
lxMS.Position = 0;
lxMS.Read(lnFile, 0, lnFile.Length);
}
}
}
using (System.IO.FileStream lxFS = new FileStream("34891.jpg", FileMode.Create))
{
lxFS.Write(lnFile, 0, lnFile.Length);
}
MessageBox.Show("done");
}
A variation of the answer, using async await for async file I/O. See Async File I/O on why this is important.
Download png and write to disk using BinaryReader/Writer
string outFile = System.IO.Path.Combine(outDir, fileName);
// Download file
var request = (HttpWebRequest) WebRequest.Create(imageUrl);
using (var response = await request.GetResponseAsync()){
using (var reader = new BinaryReader(response.GetResponseStream())) {
// Read file
Byte[] bytes = async reader.ReadAllBytes();
// Write to local folder
using (var fs = new FileStream(outFile, FileMode.Create)) {
await fs.WriteAsync(bytes, 0, bytes.Length);
}
}
}
Read all bytes extension method
public static class Extensions {
public static async Task<byte[]> ReadAllBytes(this BinaryReader reader)
{
const int bufferSize = 4096;
using (var ms = new MemoryStream())
{
byte[] buffer = new byte[bufferSize];
int count;
while ((count = reader.Read(buffer, 0, buffer.Length)) != 0) {
await ms.WriteAsync(buffer, 0, count);
}
return ms.ToArray();
}
}
}
You can use the following method to download an image from a web site and save it, using the Image class:
WebRequest req = WebRequest.Create(imageUrl);
WebResponse resp = req.GetResponse();
Image img = Image.FromStream(resp.GetResponseStream());
img.Save(filePath + fileName + ".jpg");

Categories