Using Catchoom in C# WP8.1 project - c#

i want to use catchoom in c# , but not able to find any sample could any one please provide any sample code if have.
i have got this sample of curl
curl -F "image=#CATask1-Correct.png" -F "token=sometoken" https://r.catchoom.com/v1/search
Can some one covert this to c# ?
I tried to convert it as shown below:
Here's my code:
public static async Task<string> Upload(byte[] image)
{
using (var client = new HttpClient())
{
// string boundary = "---XXX---";
using (var content = new MultipartFormDataContent())
{
string token = "sometoken";
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(token);
writer.Flush();
stream.Position = 0;
// adding Token and Image to the request
content.Add(new StreamContent(stream), "token");
content.Add(new StreamContent(new MemoryStream(image)), "bilddatei", "upload.jpg");
using (
var message = await client.PostAsync("https://r.catchoom.com/v1/search", content))
{
var input = await message.Content.ReadAsStringAsync();
return input;
}
}
}
}
then I called the method in the on-click event handler:
private async void mybtn_Click(object sender, RoutedEventArgs e)
{
// converting the image to a byte array
BitmapImage bitmapImage = new BitmapImage(new Uri("http://www.familyfuntwincities.com/wp-content/uploads/2013/09/apple_red_1_clipart.png?s=128&g=1"));
RandomAccessStreamReference rasr = RandomAccessStreamReference.CreateFromUri(bitmapImage.UriSource);
var streamWithContent = await rasr.OpenReadAsync();
byte[] buffer = new byte[streamWithContent.Size];
await streamWithContent.ReadAsync(buffer.AsBuffer(), (uint)streamWithContent.Size, InputStreamOptions.None);
// calling the upload method
string output = await Upload(buffer);
mytext1.Text = output;
}
but I keep getting "image is missing" error from the catchoom server although I managed to upload the image to other servers in the same way ( without the token part of course).
My question is: How to add multipule part content? what's the right boundary between the Token part and the image part in order to be recognized by catchoom?

Here is what worked for me:
public static async Task<string> Test(string token, Stream stream, string fileName)
{
HttpClient client = new HttpClient();
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StringContent(token), "token");
content.Add(new StreamContent(stream), "image", fileName);
var resp = await client.PostAsync("https://r.catchoom.com/v1/search", content);
return await resp.Content.ReadAsStringAsync();
}
If you wanted to use the image you listed in your sample, here is how I would fetch it:
HttpClient client = new HttpClient();
var stream = await client.GetStreamAsync("http://www.familyfuntwincities.com/wp-content/uploads/2013/09/apple_red_1_clipart.png?s=128&g=1");
return await Test("<SOME_TOKEN_VALUE>", stream, "apple.png");
However the API claims that the image is unsupported due to alpha transparency. You can find some other samples that show you how to strip alpha transparency if that is important. The above code worked fine for images that don't have alpha transparency.

Related

How do I simulate the cURL "-T [file name]" file upload behavior in .NET

I am writing a program which needs to use a RESTful API to upload files. The documentation provided only covers uploading using cURL. The sample cURL command from the documentation looks like this:
curl -X POST ^
-u ${username}:${password} ^
-H "Content-Type: application/octet-stream" ^
-H "Content-Disposition: ${file_name}" ^
-T "${file_path}" ^
-1 -k ^
--url "https://${app_server}/stream/v1/files?projectid=${projectid}"
I wrote the following methods attempting to simulate that behavior:
internal static async Task<string> Post(string filePath)
{
string fileName = new FileInfo(filePath).Name;
MemoryStream Content = ToStream(filePath);
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(Context.RESTUrl);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(#"Basic", Context.EncodedAuthHeader);
HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, Context.RESTUrl);
httpRequest.Content = new StreamContent(Content);
httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue(Constants.ContentType);
//This is my best-guess for [-H "Content-Disposition: ${file_name}"]
httpRequest.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(#"form-data")
{
Name = "fileUpload",
FileName = fileName
};
var response = httpClient.SendAsync(httpRequest).Result;
validResponse = response.StatusCode == HttpStatusCode.Created;
var contents = await response.Content.ReadAsStringAsync();
return contents;
}
}
In terms of -T "${file_path}" I'm assuming (maybe erroneously) that cURL is converting the file contents into something that can actually travel via TCP packets (a byte array), so I am passing the file as a MemoryStream in the content of the HttpRequest. Here's how I'm converting the file to a memory stream:
internal static MemoryStream ToStream(string filePath)
{
MemoryStream Result = new MemoryStream();
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
fStream.CopyTo(Result);
}
return Result;
}
The API returns a positive result, however, when I log onto the portal, although I do see the file I uploaded, the file length is 0 bytes, so I'm assuming that:
httpRequest.Content = new StreamContent(Content);
Is being ignored.
Any advice would be greatly appreciated!
The solution was to simply pass the HttpRequest content as a byte array rather than as a memory stream.
internal static async Task<string> Post(string filePath)
{
string fileName = new FileInfo(filePath).Name;
//Load the file contents into a byte array using the System.IO.File.ReadAllBytes() method.
byte[] fileBytes = File.ReadAllBytes(filePath);
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(Context.RESTUrl);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(#"Basic", Context.EncodedAuthHeader);
HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, Context.RESTUrl);
//Pass the file bytes as a ByteArrayContent object
httpRequest.Content = new ByteArrayContent(fileBytes);
httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue(Constants.ContentType);
httpRequest.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(#"form-data")
{
Name = "fileUpload",
FileName = fileName
};
var response = httpClient.SendAsync(httpRequest).Result;
validResponse = response.StatusCode == HttpStatusCode.Created;
var contents = await response.Content.ReadAsStringAsync();
return contents;
}
}

how to call web api to download document to website directory using webclient

I am struggling with being able to create a file with its data based on the byte array returned from the WebAPI. The following is my code for making the call to the web api
using (var http = new WebClient())
{
string url = string.Format("{0}api/FileUpload/FileServe?FileID=" + fileID, webApiUrl);
http.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
http.Headers[HttpRequestHeader.Authorization] = "Bearer " + authCookie.Value;
http.DownloadDataCompleted += Http_DownloadDataCompleted;
byte[] json = await http.DownloadDataTaskAsync(url);
}
The api code is
[HttpGet]
[Route("FileServe")]
[Authorize(Roles = "Admin,SuperAdmin,Contractor")]
public async Task<HttpResponseMessage> GetFile(int FileID)
{
using (var repo = new MBHDocRepository())
{
var file = await repo.GetSpecificFile(FileID);
if (file == null)
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
var stream = File.Open(file.PathLocator, FileMode.Open);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(file.FileType);
return response;
}
}
I receive a byte array as a response however am unable to create the corresponding file from that byte array. I have no idea how to convert the byte array into the relevant file type (such as jpg, or pdf based on file type in the web api). any help will be appreciated.
Alright so there are a few ways of solving your problem firstly, on the server side of things you can either simply send the content type and leave it at that or you can also send the complete filename which helps you even further.
I have removed the code that is specific to your stuff with basic test code, please just ignore that stuff and use it in terms of your code.
Some design notes here:
[HttpGet]
[Route("FileServe")]
[Authorize(Roles = "Admin,SuperAdmin,Contractor")]
public async Task<HttpResponseMessage> GetFileAsync(int FileID) //<-- If your method returns Task have it be named with Async in it
{
using (var repo = new MBHDocRepository())
{
var file = await repo.GetSpecificFile(FileID);
if (file == null)
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
var stream = File.Open(file.PathLocator, FileMode.Open);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(file.FileType);
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName=Path.GetFileName(file.PathLocator)};
return response;
}
}
Your client side code has two options here:
static void Main(string[] args)
{
using (var http = new WebClient())
{
string url = string.Format("{0}api/FileUpload/FileServe?FileID={1}",webApiUrl, fileId);
http.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
http.Headers[HttpRequestHeader.Authorization] = "Bearer " + authCookie.Value;
var response = http.OpenRead(url);
var fs = new FileStream(String.Format(#"C:\Users\Bailey Miller\Downloads\{0}", GetName(http.ResponseHeaders)), FileMode.Create);
response.CopyTo(fs); <-- how to move the stream to the actual file, this is not perfect and there are a lot of better examples
fs.Flush();
fs.Close();
}
}
private static object GetName(WebHeaderCollection responseHeaders)
{
var c_type = responseHeaders.GetValues("Content-Type"); //<-- do a switch on this and return a really weird file name with the correct extension for the mime type.
var cd = responseHeaders.GetValues("Content-Disposition")[0].Replace("\"", ""); <-- this gets the attachment type and filename param, also removes illegal character " from filename if present
return cd.Substring(cd.IndexOf("=")+1); <-- extracts the file name
}

Not receiving JSON data from Microsoft FaceAPI

I am trying to get JSON data from a picture using Microsoft's FaceAPI. I am receiving a StatusCode OK, but am not getting anything significant back. I have verified that the MemoryStream has the right data (which I am getting from an Image control) by saving it to a file.
private async Task<string> GetJSON()
{
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "mykey");
// Request parameters
queryString["returnFaceId"] = "true";
queryString["returnFaceLandmarks"] = "false";
var uri = "https://api.projectoxford.ai/face/v1.0/detect?" + queryString;
HttpResponseMessage response;
// Request body
byte[] byteData = ImageToByte();
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response = await client.PostAsync(uri, content);
}
return "";
}
private byte[] ImageToByte()
{
using (MemoryStream stream = new MemoryStream())
{
videoBox.Dispatcher.Invoke(delegate
{
var encoder = new PngBitmapEncoder();
var flippedBitmap = new TransformedBitmap();
flippedBitmap.BeginInit();
flippedBitmap.Source = (BitmapSource)videoBox.Source;
var transform = new ScaleTransform(-1, 1);
flippedBitmap.Transform = transform;
flippedBitmap.EndInit();
encoder.Frames.Add(BitmapFrame.Create(flippedBitmap));
encoder.Save(stream);
});
using (FileStream test = new FileStream("snapshot.bmp", FileMode.Create))
{
stream.Position = 0;
stream.CopyTo(test);
}
return stream.ToArray();
}
}
You'll want to call await response.Content.ReadAsStringAsync() to get the JSON.
Alternatively, you can use the Microsoft.ProjectOxford.Face NuGet package which does the plumbing for you, plus provide C# types thereby relieving you the tedium of parsing the JSON.
I am not a c# programmer but after looking at your code, method GetJSON is returning hard coded empty string that might be the cause you are not getting anything back from the server after invoking this method or second reason could be your asynchronous server configuration is not working properly thus its returning blank first and doing actual operation later.

How to post and receive a file with web api

I have a Api Post method that I want to be able to accept any file type and that looks like this:
[HttpPost]
public async Task<IHttpActionResult> Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
if (provider.Contents.Count != 1)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest,
"You must include exactly one file per request."));
}
var file = provider.Contents[0];
var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
var buffer = await file.ReadAsByteArrayAsync();
}
This works in fiddler when I try to post an image to it. However, I'm writing a client library and I have a method that looks like this:
public string PostAttachment(byte[] data, Uri endpoint, string contentType)
{
var request = (HttpWebRequest)WebRequest.Create(endpoint);
request.Method = "POST";
request.ContentType = contentType;
request.ContentLength = data.Length;
var stream = request.GetRequestStream();
stream.Write(data, 0, data.Length);
stream.Close();
var response = (HttpWebResponse) request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
Whenever I try to post an image using this, I'm getting a UnsuportedMediaType error. I'm assuming it's because my image isn't Multi Part Content? Is there an easy way to make my request of the correct type?
If I have to change my web api post method, is there an easy way of doing that without writing files to the server and keeping it in memory?
The MultipartFormDataContent from the System.Net.Http namespace will allow you to post multipart form data.
private async Task<string> PostAttachment(byte[] data, Uri url, string contentType)
{
HttpContent content = new ByteArrayContent(data);
content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
using (var form = new MultipartFormDataContent())
{
form.Add(content);
using(var client = new HttpClient())
{
var response = await client.PostAsync(url, form);
return await response.Content.ReadAsStringAsync();
}
}
}

How to send an image base64 to server windows phone 8.1

I'm developing an application on windows phone 8.1 in c# that can take a picture and send it to a server (in base64) with a post request.
So my problem is that i can't find a method which still work for include my image base64 in the body on my request and send it to my server.
private async void validPicture_Click(object sender, RoutedEventArgs e)
{
Encode("ms-appx:///xx/xxx.jpg");
try
{
var client = new Windows.Web.Http.HttpClient();
var uri = new Uri("http://x.x.x.x:x/picture/");
string pathBase64 = Encode("ms-appx:///xx/xxx.jpg").ToString();
Dictionary<string, string> pairs = new Dictionary<string, string>();
pairs.Add("type", "recognition");
HttpFormUrlEncodedContent formContent = new HttpFormUrlEncodedContent(pairs);
Windows.Web.Http.HttpResponseMessage response = await client.PostAsync(uri, formContent);
string content = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
}
}
catch (Exception eu)
{
}
}
If you are a question or need more information please tell me.
Thanks for your time.
First of all you have to read image file from storage and convert bytes to base64 string.
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(PHOTO_PATH));
byte[] rawBytes;
using (Stream stream = await file.OpenStreamForReadAsync())
{
rawBytes = new byte[stream.Length];
await stream.ReadAsync(rawBytes, 0, rawBytes.Length);
}
string base64Content = Convert.ToBase64String(rawBytes);
Then you have to make request with that content. I'm not sure how yours server accept requests but here is example of sending request with that string in content.
var httpClient = new Windows.Web.Http.HttpClient();
IBuffer content = CryptographicBuffer.ConvertStringToBinary(base64Content, BinaryStringEncoding.Utf8);
var request = new HttpBufferContent(content);
HttpResponseMessage response = await httpClient.PostAsync(new Uri(SERVER_URL), request);

Categories