Uploading Image to Imgur on Windows Phone - c#

I'm currently trying to build an app that involves the user selecting a photo from their library (or taking a photo) and uploading it to Imgur. I have already built a fairly robust C# Imgur client for Windows Forms applications, but unfortunately porting it to the Windows Phone has been a disaster.
Here is the code that I am using:
public void UploadImageAsync(Stream PhotoStream)
{
try
{
WebClient w = new WebClient();
w.Headers["Content-type"] = "application/x-www-form-urlencoded";
string data = "key="+PublicKey+
"&_fake_status=200"+
"&type=base64"+
"&image="+PhotoStreamToBase64(PhotoStream);
w.UploadStringAsync(new Uri("http://api.imgur.com/2/upload", UriKind.Absolute), "POST", data);
}
catch (Exception ex)
{
}
}
string PhotoStreamToBase64(Stream PhotoStream)
{
MemoryStream memoryStream = new MemoryStream();
PhotoStream.CopyTo(memoryStream);
byte[] result = memoryStream.ToArray();
return System.Convert.ToBase64String(result);
}
What is interesting (and frustrating) is that it appears as though everything is working fine, and I receive a successful response after the upload has completed. However, when trying to view the image after being uploaded, the result looks like this: http://i.imgur.com/NWY0R.jpg.
This leads me to believe that somehow the image stream is being converted into the byte array incorrectly, or converted into a base 64 string incorrectly. In any case, I cannot get it to work and I am at a total loss. Does anybody have any idea? Any help would be greatly appreciated.

SpikeX pushed me toward Imgur's C# API example for image uploading. Borrowing the Base64 encoding logic from their example fixed the issue. Here is the now functional PhotoStreamToBase64 method:
string PhotoStreamToBase64(Stream PhotoStream)
{
MemoryStream memoryStream = new MemoryStream();
PhotoStream.CopyTo(memoryStream);
byte[] result = memoryStream.ToArray();
string base64img = System.Convert.ToBase64String(result);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < base64img.Length; i += 32766)
{
sb.Append(Uri.EscapeDataString(base64img.Substring(i, Math.Min(32766, base64img.Length - i))));
}
return sb.ToString();
}

Related

Converting Stream to ByteString

I have Stream that I need to return through a protobuf message as bytes. How do I convert the Stream into the ByteString that is expected by protobuf? Is it as simple as it appears in the documentation Serialization?
Due to the nature of the project I'm unable to test it well so I'm kinda working blind.
Here is what I'm working with:
Protocol buffer:
message ProtoResponse {
bytes ResponseValue = 1;
}
C#
public ProtoResponse SendResponse(Stream stream)
{
var response = ProtoResponse
{
// this obviously does not work but
// but it conveys the idea of what I am going for
ResponseValue = stream
}
return response;
}
I have attempted to convert the Stream to a string or a byte[] but C# compiler in VS keeps showing this error message:
Cannot implicitly convert type '' to 'Google.Protobuf.ByteString'.
I know I am missing something and my knowledge of Streams and protocol buffers is lacking.
Actually, I may have answered my own question. ByteString has an extension that accepts a byte[].
public ProtoResponse SendResponse(Stream stream)
{
byte[] b;
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
b = memoryStream.ToArray();
}
var response = ProtoResponse
{
ResponseValue = ByteString.CopyFrom(b)
}
return response;
}
If anyone sees something wrong with this feel free to let me know! Thanks!
Im using C#, and Protobuf syntax = 3; with GRPC. In my case it looks like this:
I found method to change Image to ByteArray, this sample is here to understanding next part of my response.
private static byte[] ImageToByteArray(Bitmap image)
{
using (var ms = new MemoryStream())
{
image.Save(ms, image.RawFormat);
return ms.ToArray();
}
}
But, next i have to change Bytearray to ByteString of Protobuf3
byte[] img = ImageToByteArray(); //its method you can see above
ByteString bytestring;
using (var str = new MemoryStream(img))
{
bytestring = ByteString.FromStream(str);
}
You can simply use ByteString.FromStream(MemoryStream) without CopyFrom method.
If we take a look to receiver of this message, he need change ByteString to ByteArray to for example save photo:
byte[] img = request.Image.ToByteArray(); //this is received message
And thats all. You have exactly the same bytes in both sides.

Unable to create stream from stored image for byte[] conversion

I've been struggling with this implementation for a few hours now and can't seem to find any solutions wherever I look (SO, Xamarin Forums, Google etc)...
In this current scenario I have a few images in .Droid.Resources.Drawable which I wish to access and convert into a byte[] from my shared code. This is due to the fact that I wish to test the full span of my CRUD functionality on a REST API I've set up as an end-point for our server.
The images show up fine in the application, but for some reason I simply can't seem to warp my head around the process of converting these images to a byte[] in Xamarin. I've done it countless times in 'normal' C#...
Sorry if the code is a bit messy, but I'm sure you get the idea.
I want to get an image from .Droid storage (will be ported for iOS later)
Convert said image into a byte[]
Send that byte[] representation to my API.
In the code's current state I'm getting this error:
C#: An instance of an abstract class can not be created
Where I'm attempting to create a new Stream (new Stream(sauce))
The below example is based on snippets found here and full credit goes to Sten and Vincent.
/*
* Takes an arbitrary string as a token, updates a record with dummy data and a placeholder_image.
*/
public async Task<string> PostUpdateFoundation(string arbitrary, Image img)
{
ImageSource sauce = ImageSource.FromFile("abc.png");
byte[] byte_img = FromStreamToByte(new Stream(sauce)); //error occurs here
Debug.WriteLine("I'm in!");
var client = new System.Net.Http.HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
var content = new StringContent(arbitrary);
var response = await client.PostAsync(String.Format("http://some.api.to.test.com?s={0}&img={1}", arbitrary, byte_img), content);
var result = response.Content.ReadAsStringAsync().Result;
return result;
}
/*
* Attempts to convert an stream (based on image source) into a byte[].
*/
public static byte[] FromStreamToByte (Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
Try using Plugin.Media
byte BImageSource = ReadFully(file.GetStream());
var bytes = new byte[file.GetStream().Length]; //file is from the plugin and contains your image
file.GetStream().Position = 0;
file.GetStream().Read(bytes, 0, (int)file.GetStream().Length);
BImageSource = ReadFully(file.GetStream()); //BImageSource is your resource in bytes
byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
Hope this helps!

AddAttachment from MemoryStream

The SendGrid API docs specify you can add attachments from a Stream. The example it gives uses a FileStream object.
I have some blobs in Azure Storage which I'd like to email as attachments. To achieve this I'm trying to use a MemoryStream:
var getBlob = blobContainer.GetBlobReferenceFromServer(fileUploadLink.Name);
if(getBlob != null)
{
// Get file as a stream
MemoryStream memoryStream = new MemoryStream();
getBlob.DownloadToStream(memoryStream);
emailMessage.AddAttachment(memoryStream, fileUploadLink.Name);
}
emailTransport.Deliver(emailMessage);
It sends fine but when the email arrives, the attachment appears to be there but it's actually empty. Looking at the email source, there is no content for the attachment.
Is using a MemoryStream a known limitation when using the SendGrid C# API to send attachments? Or should I be approaching this in some other way?
You probably just need to reset the stream position back to 0 after you call DownloadToStream:
var getBlob = blobContainer.GetBlobReferenceFromServer(fileUploadLink.Name);
if (getBlob != null)
{
var memoryStream = new MemoryStream();
getBlob.DownloadToStream(memoryStream);
memoryStream.Seek(0,SeekOrigin.Begin); // Reset stream back to beginning
emailMessage.AddAttachment(memoryStream, fileUploadLink.Name);
}
emailTransport.Deliver(emailMessage);
You might want to check who cleans up the stream as well and if they don't you should dispose of it after you've called Deliver().
According to their API, they have implemented void AddAttachment(Stream stream, String name).
You are probably using a MemoryStream which you have written to before. I suggest resetting the position inside the stream to the beginning, like:
memoryStream.Seek(0, SeekOrigin.Begin);
I ended up with the following which fixed the issue for me:
fileByteArray = new byte[getBlob.Properties.Length];
getBlob.DownloadToByteArray(fileByteArray, 0);
attachmentFileStream = new MemoryStream(fileByteArray);
emailMessage.AddAttachment(attachmentFileStream, fileUploadLink.Name);
The thread is a bit old, but I use a varient with NReco PDF converter:
private async Task SendGridasyncBid(string from, string to, string displayName, string subject, **byte[] PDFBody**, string TxtBody, string HtmlBody)
{
...
var myStream = new System.IO.MemoryStream(**PDFBody**);
myStream.Seek(0, SeekOrigin.Begin);
myMessage.AddAttachment(myStream, "NewBid.pdf");
...
}
convert the html to pdf and return it instead of writing it for download...
private byte[] getHTML(newBidViewModel model)
{
string strHtml = ...;
HtmlToPdfConverter pdfConverter = new HtmlToPdfConverter();
pdfConverter.CustomWkHtmlArgs = "--page-size Letter";
var pdfBytes = pdfConverter.GeneratePdf(strHtml);
return **pdfBytes**;
}
I am not sure how efficient this is, but it is working for me and I hope it helps someone else get their attachments figured out.

Sending image with byte array convertion, from java to c#

I am trying to send a .jpg file which is on my android device to my server computer.
To do this, I am converting the picture into a byte array by a java android application, and sending it as an argument to my server computer. I`m doing this by a web service call.
The first function is edited:
public static byte[] ImageConvertion(){
File inputFile = new File("/storage/emulated/0/IFSpictures/icon-si_strapclamp.jpg");
byte[] data;
try{
FileInputStream input = new FileInputStream(inputFile);
ByteArrayOutputStream output = new ByteArrayOutputStream ();
byte[] buffer = new byte[65535];
int l;
while ((l = input.read(buffer)) > 0)
output.write (buffer, 0, l);
input.close();
output.close();
data = output.toByteArray();
return data;
} catch (IOException e) {
System.err.println(e);
data=null;
}
return data;
}
My web-service is written in ASP.NET (C#) language, and there is a function that takes the byte array as an argument and converts it back into an image on server computer.
[WebMethod]
public void ByteArrayToPicture(byte[] imageData)
{
using (var ms = new MemoryStream(imageData))
{
Image image = Image.FromStream(ms);
image.Save(#"C:\newImage.jpg");
}
}
However, I couldn`t do it because of the web-service side. I have debugged it that and it seems that the problem is because of the Image.FromStream() function.
I definitely don`t have any problems with passing the arguments. I think either, the language conflict or the conversion image to byte and vice-verse may be leading the problem. Does anyone has any idea or see something wrong?
I muchly appropriate any help.
Thanks.
sorry for my incomplete question, however I want to give some tips whoever is trying to do the same thing.
If anyone is trying to send an image to a server and both side has different platforms, then do not convert the image into byte array!
The reason is, in my case the image which is converted into byte array on Java differs from the byte array on C#. Therefore according to my research it is not possible to gather the image on the server side. The byte array created on Java wont have the right format on C#.
Hence anyone wants data transferring from one language to another, use Base64 encoding. Convert the image into Base64 string on one side and send it as string to the other language. Since Base64 format is same on every language there wont be any problem to reproduce it.
I sold the problem with the following codes:
Bitmap ourbitmap = BitmapFactory.decodeStream(imageStream, null, options);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ourbitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
test = Base64.encodeToString(b, Base64.DEFAULT);
This is the code where I get the image and convert it into Base64 string on Java android application,
byte[] imageBytes = Convert.FromBase64String(Base64ImageData);
MemoryStream ms = new MemoryStream(imageBytes, 0,
imageBytes.Length);
ms.Write(imageBytes, 0, imageBytes.Length);
Image image = Image.FromStream(ms, true);
image.Save(#"D:\tmpImage.jpg");
The code above takes the Base64 type string and converts back into an image. This is written in C#.
With such an incomplete code example and such a vague problem description, it's difficult to know for sure what the problem is.
However, reviewing the code you did post, I see one bug that would be significant if this is really the code you are using. In your Java methodConvertion() method, you have this statement:
data = output.toByteArray();
The problem is that all that does is create a new byte[] object and assign the reference to your local variable named data. That object never leaves the method.
Presumably you have some other code which, after calling methodConvertion(), sends the byte[] object that is referenced by the argument you passed to that method. But that object is just going to be whatever it was before you called the method.
You should instead change your Java code so that it looks like this:
public static byte[] methodConvertion(){
File inputFile = new File("/storage/emulated/0/IFSpictures/icon-si_strapclamp.jpg");
try{
FileInputStream input = new FileInputStream(inputFile);
ByteArrayOutputStream output = new ByteArrayOutputStream ();
byte [] buffer = new byte [65536];
int l;
while ((l = input.read(buffer)) > 0)
output.write (buffer, 0, l);
input.close();
output.close();
return output.toByteArray();
} catch (IOException e) {
System.err.println(e);
return null;
}
}
And then in the caller, you should check the return value and only proceed if the value is not null, reporting the error somehow otherwise.
If that doesn't address your question, you should edit the question so that it has a better code example, and so that you are much more specific about what's wrong. What happens when you run the code, and how is that different from what you expected? Be sure to clearly state any error messages, quoting them exactly, and including any stack traces from exceptions.

how can be possible to programmatically upload and retrieve photos from PicasaWeb in C#

Is it possible to use PicasaWeb to host photos for my website? My requirement to upload and access within my ASP.NET Website.
Yes, technically. You can use the Picasa Web Albums Data API to access the metadata about your images and then display them from Picasa. For an album, this is not a horrible idea, but I would not use this method for your site graphics.
public string UploadImage(byte[] imageBytes_, string imageName_)
{
string url = string.Empty;
try
{
PicasaEntry newPhoto = null;
MemoryStream ms = new MemoryStream();
ms.Write(imageBytes_, 0, imageBytes_.Length);
if (_albumFeed != null)
{
PicasaEntry photoEntry = new PhotoEntry();
photoEntry.MediaSource = new Google.GData.Client.MediaFileSource(ms, imageName_, "image/jpeg");
newPhoto = this._service.Insert<PicasaEntry>(new Uri(this._albumFeed.Post), photoEntry);
}
url = newPhoto.FeedUri;
}
catch (Exception ex)
{
throw new DneException("Error while uploading photo", ex );
}
return url ;
}
I am uploading a zipped images and extracting using SharpZipLib library. I am getting each file in chunk of bytes and which I am converting into MemoryStream later to pass the MediaSource object. I am getting 400 Bad Request error each time. When I am passing FileStream, it works fine but doesn't work with MemoryStream

Categories

Resources