Error 404 using MS Cognitive services Image Analysis demo code - c#

Using the code from the MS Cognitive services example app at https://learn.microsoft.com/en-us/azure/cognitive-services/computer-vision/quickstarts/csharp I get Error 404 when trying to run the following code with imageFilePath set a local JPEG file:
static async void MakeAnalysisRequest(string imageFilePath)
{
HttpClient client = new HttpClient();
// Request headers.
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
// Request parameters. A third optional parameter is "details".
string requestParameters = "visualFeatures=Description&language=en";
// Assemble the URI for the REST API Call.
string uri = uriBase + "?" + requestParameters;
HttpResponseMessage response;
// Request body. Posts a locally stored JPEG image.
byte[] byteData = GetImageAsByteArray(imageFilePath);
using (ByteArrayContent content = new ByteArrayContent(byteData))
{
// This example uses content type "application/octet-stream".
// The other content types you can use are "application/json" and "multipart/form-data".
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
// Execute the REST API call.
response = await client.PostAsync(uri, content);
// Get the JSON response.
string contentString = await response.Content.ReadAsStringAsync();
// Display the JSON response.
Console.WriteLine("\nResponse:\n");
Console.WriteLine(JsonPrettyPrint(contentString));
}
subscriptionKey is KEY1 from the two keys provided with my Azure subscription (in Eastern Australia location) and uribase is
const string uriBase = "https://australiaeast.api.cognitive.microsoft.com/vision/v1.0";
The combination of KEY1 and uriBase works OK with the demo of the API at
https://australiaeast.dev.cognitive.microsoft.com/docs/services/56f91f2d778daf23d8ec6739/operations/56f91f2e778daf14a499e1fa/console
when the target file is a URL rather than a local file. The image is correctly analyzed.
Why am I getting the 404 error when trying to post from C#? Is it the fact that I am using content type application/octet-stream?
Code for GetImageAsByteArray is:
static byte[] GetImageAsByteArray(string imageFilePath)
{
FileStream fileStream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read);
BinaryReader binaryReader = new BinaryReader(fileStream);
return binaryReader.ReadBytes((int)fileStream.Length);
}

You're missing the last portion of the request URI. It should be:
string uri = uriBase + "/analyze?" + requestParameters;

Related

send file using HttpClient in PostAsync using function app in req.Form.Files c#

I have created Function App for uploading multiple files on FTP server. I have received all files using req.Form.Files. but When I get the request. I actually found my file from HttpClient request in req.Body. When I upload file from Postman in Body->FormData it, works fine but now I need to send post request with file by code.
I had tried below code with reference of Sending a Post using HttpClient and the Server is seeing an empty Json file this link.
HttpContent content = new StreamContent (stream);
content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
HttpResponseMessage response = client.PostAsync ("url", content).Result;
But I want file in req.Form.Files . Where user might have uploaded multiple files or one file.
Note : For now I have a file which is being generated by code. But it should not be saved on local so I'm trying to send stream. in HttpContent
Below are the steps for Post Async using function app
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req, ILogger log)
{
string Connection = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
string containerName = Environment.GetEnvironmentVariable("ContainerName");
var file = req.Form.Files["File"];**
var filecontent = file.OpenReadStream();
var blobClient = new BlobContainerClient(Connection, containerName);
var blob = blobClient.GetBlobClient(file.FileName);
byte[] byteArray = Encoding.UTF8.GetBytes(filecontent.ToString());
File details while using req.Form.Files
Successfully uploaded a text file to blob storage.
Edit:
Here is the Post request Using HttpClient
var file = #"C:\Users\...\Documents\test.txt";
await using var stream = System.IO.File.OpenRead(file);
using var request = new HttpRequestMessage(HttpMethod.Post, "file");
using var content = new MultipartFormDataContent
{
{ new StreamContent(stream),"File", "test.txt" }
};
request.Content = content;
await client.SendAsync(request);
return new OkObjectResult("File uploaded successfully");

Rewriting a Java HttpURLConnection method using C# HttpClient

I've got a working Java method that uses java.net.HttpURLConnection that I should re-implement in C# using the .NET HttpClient.
Java method:
public static String getMyThingAPIToken() throws IOException{
URL apiURL = new URL("https://myThingAPI/token");
HttpURLConnection apiConnection = (HttpURLConnection) apiURL.openConnection();
apiConnection.setRequestMethod("POST");
apiConnection.setDoOutput(true);
String apiBodyString = "myThingAPI login id and secret key";
byte[] apiBody = apiBodyString.getBytes(StandardCharsets.UTF_8);
OutputStream apiBodyStream = apiConnection.getOutputStream();
apiBodyStream.write(apiBody);
StringBuffer apiResponseBuffer;
try (BufferedReader in = new BufferedReader(new InputStreamReader(apiConnection.getInputStream()))){
String inputline;
apiResponseBuffer = new StringBuffer();
while((inputline = in.readLine()) != null) {
apiResponseBuffer.append(inputline);
}
}
}
So far, my C# looks like below, and you'll notice that this early form of my implementation does not interpret the response. Nor does it have a string return type required for the token string.
This is because when I test it, the response has:
StatusCode: 400
ReasonPhrase: 'Bad Request'
So something in my apiBody byte array or use of PostAsync must be different to what the Java method does, but I cannot work out what it could be.
public async static Task<HttpResponseMessage> getMyThingAPIToken(HttpClient client)
{
var apiURI = new Uri("https://myThingAPI/token");
string apiBodystring = "myThingAPI login id and secret key";
byte[] apiBody = System.Text.Encoding.UTF8.GetBytes(apiBodystring);
var response = await client.PostAsync(apiURI, new ByteArrayContent(apiBody));
return response;
}
The Java code doesn't specify a type which means that by default the request uses application/x-www-form-urlencoded. This is used for FORM POST requests.
The default content type for ByteArrayContent on the other hand is application/octet-stream while for StringContent it's text/plain.
FORM content is used through the FormUrlEncoodedContent class which can accept any Dictionary<string,string> as payload.
The input in the question is not in a x-www-form-urlencoded form so either it's not the real content or the API is misusing content types.
Assuming the API accepts proper x-www-form-urlencoded content, the following should work:
var data=new Dictionary<string,string>{
["login"]=....,
["secret"]=.....,
["someOtherField"]=....
};
var content= new FormUrlEncodedContent(data);
var response=await client.PostAsync(apiURI,content);
To send any text using application/x-www-form-urlencoded, we need to specify the content type in StringContent's constructor:
var contentType="application/x-www-form-urlencoded";
var content= new StringContent(apiBodyString, Encoding.UTF8,contentType);
var response=await client.PostAsync(apiURI,content);
Can you try using following code:
client.BaseAddress = new Uri("https://myThingAPI/");
var message = new HttpRequestMessage(HttpMethod.Post, "/token");
// Add your login id and secret key here with the format you want to send
message.Content = new StringContent(string.Format("userName={0}&password={1}", UserName, Password));
var result = await client.SendAsync(message);
return result;

Microsoft cognitive service Recognize Text api

I call the microsoft recognize text api by passing the image that I had taken from my phone, there no error occur but every time the api will return me empty string as result doesn't matter what image I post . I try those image with the microsoft ocr api and it return me result, can anyone help ?
I call the microsoft recognize text api by passing the image that I had taken from my phone, there no error occur but every time the api will return me empty string as result doesn't matter what image I post.
In documentation of Recognize Text API, we can find:
The service has accepted the request and will start processing later.
It will return Accepted immediately and include an “Operation-Location” header. Client side should further query the operation status using the URL specified in this header.
I suspect that you directly get/extract content from the response after you made a request to recognize text, so the content would be string.Empty.
To get recognize text operation result, you need to make a further request using the URL specified in response header "Operation-Location".
In following test code, we can find the content is indeed empty.
Test Code:
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{Subscription_Key_here}");
queryString["mode"] = "Printed";
var uri = "https://{region}.api.cognitive.microsoft.com/vision/v2.0/recognizeText?" + queryString;
HttpResponseMessage response;
var imagePath = #"D:\xxx\xxx\xxx\testcontent.PNG";
Stream imageStream = File.OpenRead(imagePath);
BinaryReader binaryReader = new BinaryReader(imageStream);
byte[] byteData = binaryReader.ReadBytes((int)imageStream.Length);
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response = await client.PostAsync(uri, content);
if (response.IsSuccessStatusCode)
{
var contentString = await response.Content.ReadAsStringAsync();
var operation_location = response.Headers.GetValues("Operation-Location").FirstOrDefault();
Console.WriteLine($"Response content is empty({contentString == string.Empty}).\n\rYou should further query the operation status using the URL ({operation_location}) specified in response header.");
}
}
Test Result:
Note: Recognize Text API is currently in preview and is only available for English text. As you mentioned, OCR technology in Computer Vision can also help detect text content in an image, and OCR currently supports 25 languages, sometimes we can use OCR as an alternative solution.

How to handle png from rest api?

Right now, I'm creating a WCF service that sends a location to the Bing Map API and returns a PNG image to the service client. Currently, I copied a working api example from their documentation webpage, and I'm having a hard time figuring out how I can pass it on.
From other stackoverflow questions, I started by converting the response, and I got it into Base64. But it triggered and received an error, that says input is not in Base64 form.
A screenshot of what input looks like
public string getResponse()
{
string key = [My Api Key];
Uri geocodeRequest = new Uri(string.Format("http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}", query, key));
Uri imageryRequest = new Uri(string.Format("https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/Redmond Washington?ms=500,270&zl=12&&c=en-US&he=1&key={0}", key));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imageryRequest);
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
//Handling the response in PNG
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string input = reader.ReadToEnd();
byte[] data = convert.FromBase64String(input);
return data;
}
It already is a PNG image as byte[]. Also, keep in mind that the image returned is not guaranteed to be PNG, JPEG, or GIF. It returns what it feels is the most appropriate image type unless a specific type is requested.
ex. fmt=jpeg
You just need to do something with it. In my example, I saved it to a file. You probably just need to return the byte[].
private static HttpClient client = new HttpClient();
public static async void GetResponse()
{
string key = Properties.Settings.Default.Key;
Uri imgUri = new Uri($"https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/Redmond Washington?ms=500,270&zl=12&&c=en-US&he=1&fmt=png&key={key}");
HttpResponseMessage response = await client.GetAsync(imgUri);
response.EnsureSuccessStatusCode();
byte[] responseData = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("test.png", responseData);
}

Microsoft Cognitive Services Vision API: Sending multipart data

I am trying to call the Microsoft Cognitive API by passing multiple images as per documentation and using the multipart/form-data, but I am getting an error that says "Unsupported Media Type". I have tried to use both ByteArray and StreamContent.
Api documentation.
private static byte[] GetImageAsByteArray(Stream fileStream)
{
using (var binaryReader = new BinaryReader(fileStream))
{
return binaryReader.ReadBytes((int)fileStream.Length);
}
}
static void Main(string[] args)
{
var uriBase = "https://westus.api.cognitive.microsoft.com/vision/v1.0/recognizeText";
var subscriptionKey = "<subscriptionKey>";
var client = new HttpClient();
var uri = string.Concat(uriBase, "?", "language=en&detectOrientation=true");
var images = new List<Stream>();
var img = Image.FromStream(File.Open("<imageName>", FileMode.Open));
var stream = new MemoryStream();
img.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
images.Add(stream);
using (var content = new MultipartFormDataContent())
{
foreach (var image in images)
{
//content.Add(new StreamContent(stream));
content.Add(new ByteArrayContent(GetImageAsByteArray(image)));
}
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
var response = client.PostAsync(uri, content).Result;
}
}
I am trying to call the Microsoft Cognitive API by passing multiple images as per documentation and using the multipart/form-data, but I am getting an error that says "Unsupported Media Type".
It is not possible to send multiple images, regardless of header.
Please refer to the documentation Step 2, it mentions:
The basic way to perform the Computer Vision API call is by uploading an image directly. This is done by sending a "POST" request with application/octet-stream content type together with the data read from the image.
Example code can be found here
Test environment here.
Notice regardless of header, it is still sending 1 image.
The limits also mention a single image.

Categories