"No file uploaded or URL provided" when calling ocr.space API - c#

I'm trying to call this API from my C# app:
https://ocr.space/OCRAPI
When I call it from curl, it just works fine:
curl -k --form "file=#filename.jpg" --form "apikey=helloworld" --form "language=eng" https://api.ocr.space/Parse/Image
I implemented it this way:
[TestMethod]
public async Task Test_Curl_Call()
{
var client = new HttpClient();
String cur_dir = Directory.GetCurrentDirectory();
// Create the HttpContent for the form to be posted.
var requestContent = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>( "file", "#filename.jpg"), //I also tried "filename.jpg"
new KeyValuePair<string, string>( "apikey", "helloworld" ),
new KeyValuePair<string, string>( "language", "eng")});
// Get the response.
HttpResponseMessage response = await client.PostAsync(
"https://api.ocr.space/Parse/Image",
requestContent);
// Get the response content.
HttpContent responseContent = response.Content;
// Get the stream of the content.
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
// Write the output.
String result = await reader.ReadToEndAsync();
Console.WriteLine(result);
}
}
I get this answer :
{
"ParsedResults":null,
"OCRExitCode":99,
"IsErroredOnProcessing":true,
"ErrorMessage":"No file uploaded or URL provided",
"ErrorDetails":"",
"ProcessingTimeInMilliseconds":"0"
}
Any clue?
What's the # character for in "file=#filename.jpg"?
I put my filename.jpg file in the project and test project bin/debug directory and run my test project in debug mode.
So I don't think the error points to the file not being where expected.
I'd rather suspect a syntax error in my code.

The error message is telling you what's wrong:
No file uploaded or URL provided
You sent a filename to the service in your code, but that's not the same thing as giving curl a filename. curl is smart enough to read the file and upload the contents with your request, but in your C# code, you'll have to do that yourself. The steps will be:
Read the file bytes from disk.
Create a multipart request with two parts: the API key ("helloworld"), and the file bytes.
POST this request to the API.
Fortunately, it's pretty easy. This question demonstrates the syntax to set up a multipart request.
This code worked for me:
public async Task<string> TestOcrAsync(string filePath)
{
// Read the file bytes
var fileBytes = File.ReadAllBytes(filePath);
var fileName = Path.GetFileName(filePath);
// Set up the multipart request
var requestContent = new MultipartFormDataContent();
// Add the demo API key ("helloworld")
requestContent.Add(new StringContent("helloworld"), "apikey");
// Add the file content
var imageContent = new ByteArrayContent(fileBytes);
imageContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
requestContent.Add(imageContent, "file", fileName);
// POST to the API
var client = new HttpClient();
var response = await client.PostAsync("https://api.ocr.space/parse/image", requestContent);
return await response.Content.ReadAsStringAsync();
}

Related

Docusign | Why is API returning "resource does not support http method 'POST'" | C#

I am trying to upload a file to springCM and receiving this message:
"The requested resource does not support http method 'POST'."
Hitting endpoint:
....springcm.com/v201411/folders/{folderGUID}/documents
Which matches their documentation:
The name is optional, but I've tried passing that in the URL and as a parameter as well.
Here is what I believe to be the relevant code:
Uri uri = new Uri("https://....springcm.com/v201411/folders/32dsdfdb-9356-eb11-b875-45df378sdfds/documents");
Stream uploadFile = File.OpenRead(filePath + fileName);
HttpContent fileStreamContent = new StreamContent(uploadFile);
using (client = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileStreamContent);
var response = await client.PostAsync(uri, formData);
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
await response.Content.ReadAsStreamAsync();
}
What could I be doing wrong here?
TIA!
You need to use the correct subdomain, which should start with apiupload. The complete URL should look like this:
https://apiupload[datacenter].springcm.com/[api version]/folders/[folder identifier]/documents{?name}
More information: https://developers.docusign.com/docs/clm-api/clm101/content-api/

Sending a POST request with FILE using in XAMARIN C#

looking on the web, I saw a little bit how to POST a 'file' and therefore, I wrote my code in this way:
var upfilebytes = File.ReadAllBytes((string)fPath);
//create new HttpClient and MultipartFormDataContent and add our file, and StudentId
HttpClient client = new HttpClient();
MultipartFormDataContent content = new MultipartFormDataContent();
ByteArrayContent baContent = new ByteArrayContent(upfilebytes);
content.Add(baContent, "img", fPath);
StringContent emailText = new StringContent(lbl_email.Text);
content.Add(emailText, "email");
string url = "http://192.168.178.77/TestLoginURL/api/updateUserImage.php";
//upload MultipartFormDataContent content async and store response in response var
var response =
await client.PostAsync(url, content);
//read response result as a string async into json var
var responsestr = response.Content.ReadAsStringAsync().Result;
now the problem is another ... this is my API code:
<?php
$response = array();
if($_SERVER['REQUEST_METHOD']=='POST'){
//getting values
$img = $_FILES['img']['name'];
$email = $_POST['email'];
//including the db operation file
require_once '../includes/DbOperation.php';
$db = new DbOperation();
$target = "/Applications/XAMPP/xamppfiles/htdocs/TestLoginURL/images/".basename($img);
//inserting values
if($db->updateImage((String)basename($img),$email)){
$response['error']=false;
$response['message']='Image added successfully - test fileName = '.(String)basename($img);
}else{
$response['error']=true;
$response['message']='Could not add image';
}
if(move_uploaded_file($_FILES['img']['tmp_name'], $target)) {
/*$response['error']=false;
$response = "Image uploaded successfully";*/
}else{
$response['error']=true;
$response = "Failed to upload image";
}
}else{
$response['error']=true;
$response['message']='You are not authorized';
}
echo json_encode($response);
With Postman it works perfectly, updates the name of the image in the database and physically inserts the image in the designated path and the response message for example is this: {"error": false, "message": "Image added successfully - test fileName = trollolollo.png"}
Now, the app saves the file in the right repository but does NOT UPDATE the name of the 'image' in the database ... BUT strangely, the "response" message in the debugger also correctly shows the name of the FILE ... So I just don't understand where I'm wrong ... Could someone help me with the code please? Thanks
OFF_TOPIC: usually, when I have to send only strings, I send a post request written in this way
string url = "http://192.168.178.77/TestLoginURL/api/insertUser.php";
FormUrlEncodedContent formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("nickname", nickname),
new KeyValuePair<string, string>("password", password1),
new KeyValuePair<string, string>("email", email)
});
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
try
{
CancellationTokenSource cts = new CancellationTokenSource();
var responseMessage = httpClient.PostAsync(url, formContent).Result;
}
catch (Exception ex)
{
ex.Message.ToString();
throw;
}
but now, being a file and having no experience about it I am having difficulties...
thanks again, I hope someone can help me with the code
Are you sure that you are handling update query correctly ?
Update query will only return false on a failure if you messed up the SQL query or anything like that. So you have to use mysqli_stmt_affected_rows to see if a row has been updated in your PHP code.
If postman can do it HttpClient must be able to do it too, with the proper configuration.
Try to use all the headers postman is using you are probably missing something, maybe the filename is causing the DB query to fail.
By the way is there any difference between how you handle jpg and png in your server ? you can check that too.

Can't get Microsoft.ProjectOxford.Vision or REST method working in PCL

This should be pretty straightforward, but I can't get it to work. I'm using these instructions. I've tried using the Nuget package in my PCL targeting 259 as as well as in another PCL targeting 7. Both PCLs never return after these lines. I've tried both.
//text = await client.RecognizeTextAsync(imageURL);
text = await client.RecognizeTextAsync(imageURL, languageCode: "en", detectOrientation: true);
Here is the REST code I've also tried. This works with my HTTP Helper.
public static async Task<OcrResults> PostReceiptAsync(string imageURL)
{
try
{
var apiKey = "KEY 1";
var content = await HttpHelper.Request(null, String.Format("https://eastus2.api.cognitive.microsoft.com/vision/v1.0?language=en&detectOrientation=true&subscription-key={0}&url={1}", apiKey, imageURL), null, HttpRequestType.POST);
return Mapper<OcrResults>.MapFromJson(await content.ReadAsStringAsync());
}
catch (Exception e)
{
throw;
}
}
In both methods, I'm trying to use a Blob image URL. Here is my calling method.
takePhoto.Clicked += async (sender, args) =>
{
}
It's almost seems like a deadlock issue.
Any help is much appreciated. Thanks!
UPDATE: I finally got the REST method to work with Android and UWP using this bit of code, but it fails in my iOS app. The main problem I had is that the URL that you copy out of Azure does not include the ocr? parameter. The Json Mapper is something that my SDK uses. OcrResults comes from the Project Oxford Nuget package.
public static async Task<OcrResults> ProcessReceiptAsync(string imageUrl)
{
// Instantiate a HTTP Client
var client = new HttpClient();
var apiKey = "KEY 1";
// Request parameters and URI
string requestParameters = "language=en&detectOrientation =true";
string uri = "https://eastus2.api.cognitive.microsoft.com/vision/v1.0/ocr?" + requestParameters;
// Pass subscription key thru the HTTP Request Header
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
// Format Request body
byte[] byteData = Encoding.UTF8.GetBytes($"{{\"url\": \"{imageUrl}\"}}");
using (var content = new ByteArrayContent(byteData))
{
// Specify Request body Content-Type
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
// Send Post Request
HttpResponseMessage response = await client.PostAsync(uri, content);
// Read Response body into the model
//return await response.Content.ReadAsStringAsync(OcrResults);
var result = Mapper<OcrResults>.MapFromJson(await response.Content.ReadAsStringAsync());
return result;
}
}
UPDATE 2: This method also works on Android and UWP, but fails with a BadRequest in my iOS app. I wanted to change up how the image URL gets encoded.
public static async Task<OcrResults> ProcessReceiptAsync2(string imageUrl)
{
// Instantiate a HTTP Client
var client = new HttpClient();
var apiKey = "KEY 1";
// Request parameters and URI
string requestParameters = "language=en&detectOrientation =true";
string uri = "https://eastus2.api.cognitive.microsoft.com/vision/v1.0/ocr?" + requestParameters;
// Pass subscription key thru the HTTP Request Header
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
// Format Request body
var dict = new Dictionary<string, string>();
dict.Add("url", imageUrl);
//var param = JsonConvert.SerializeObject($"{{\"url\": \"{imageUrl}\"}}");
var param = JsonConvert.SerializeObject(dict);
HttpContent contentPost = new StringContent(param, Encoding.UTF8, "application/json");
// Specify Request body Content-Type
//contentPost.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Send Post Request
HttpResponseMessage response = await client.PostAsync(uri, contentPost);
// Read Response body into the model
//return await response.Content.ReadAsStringAsync(OcrResults);
var result = Mapper<OcrResults>.MapFromJson(await response.Content.ReadAsStringAsync());
return result;
}
UPDATE 3: I tried this code, but it failed with a Bad Request on iOS. I'm using the ExtractTextFromImageUrlAsync. I did get a "file too large" error using the ExtractTextFromImageStreamAsync, so that method appears to have worked.
https://github.com/HoussemDellai/Microsoft-Cognitive-Services-API/blob/master/ComputerVisionApplication/ComputerVisionApplication/Services/ComputerVisionService.cs
UPDATE 4: I removed Microsoft.Net.Http 2.9 from all the Projects and commented out System.Net.Http from all the app.config files. Both methods now work in the Android and UWP app. I still can't get the iOS app to work. The Project Oxford Nuget fails at this line requestObject.url = imageUrl; (see GitHub). The Rest method fails with a Bad Request, but I managed to catch a "InvalidImageUrl" message, so something is happening when the imageUrl is encoded. At this stage, I believe this is a Xamarin issue that's specific to iOS 10.4.0.

C# Request - API LiveChat

i've been following this Making a cURL call in C# for trying to make a request with the LiveChat API in curl and receive the result on my C# application,
the request should be filled as the following as explained in: http://developers.livechatinc.com/rest-api/#!introduction
curl "https://api.livechatinc.com/agents" \
-u john.doe#mycompany.com:c14b85863755158d7aa5cc4ba17f61cb \
-H X-API-Version:2
This is what i did in C#:
static void Main(string[] args)
{
RequestTest();
Console.ReadKey();
}
private static async void RequestTest()
{
var client = new HttpClient();
// Create the HttpContent for the form to be posted.
var requestContent = new FormUrlEncodedContent(new[] {new KeyValuePair<string, string>("myemail:myapikey", "X-API-Version:2"),});
// Get the response.
HttpResponseMessage response = await client.PostAsync(
"https://api.livechatinc.com/agents",
requestContent);
// Get the response content.
HttpContent responseContent = response.Content;
// Get the stream of the content.
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
// Write the output.
Console.WriteLine(await reader.ReadToEndAsync());
}
}
The result seems to be allways the same "Cannot POST to /agents"
You're performing a POST operation here. That is reserved for creating a new agent and requires that you send in a JSON request payload. See here:
developers.livechatinc.com/rest-api/#create-agent
What you want to do is a GET operation:
developers.livechatinc.com/rest-api/#get-single-agent
Instead of using PostAsync you'll need to create an HttpRequestMessage, set the Method to GET, set your headers and then use SendAsync. See solution here: Adding Http Headers to HttpClient
Remember, for REST API:
POST = Create Operations,
GET = Read Operations,
PUT = Update Operations,
DELETE = Delete Operations

HttpClient PostAsync List<string> instead of file.csv

I am attempting to post content to a vendor. The data uploads when I save my data to a .csv then reference the file. What I would prefer to do is skip saving the file to disk and just upload the data. I can't seem to figure out how to serialize the data correctly.
Here is the data:
csv.Add(string.Join(",", "sara1234", "Ancient World Studies-1201A1-01"));
csv.Add(string.Join(",", "jazzy4567", "Ancient World Studies-1201A1-01"));
Here is the upload:
protected async Task<bool> RunAsync(string baseAddress, IEnumerable<string> file, string passkey)
{
byte[] csvBytes = File.ReadAllBytes("C:\\Projects\\AutomationServiceFiles\\DataMig_Test\\Drop\\Hapara\\HaparaStudent.csv");
var csvContent = new ByteArrayContent(csvBytes);
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
content.Add(new StringContent(passkey), "passkey");
content.Add(csvContent, "uploadFile", "student.csv");
var response = await client.PostAsync(baseAddress, content);
response.EnsureSuccessStatusCode();
string returnedContent = await response.Content.ReadAsStringAsync();
}
}
return true;
}
I have tried what's shown below (instead of the file from disk). I get a 200 success message back, but data does not load. Specifically, the first method returns a message that the students were not found (this is good because I know the data was evaluated), the second returns no message at all.
string jsonFile = JsonConvert.SerializeObject(file);
HttpContent contentPost = new StringContent(jsonFile, Encoding.UTF8, "application/json");
content.Add(contentPost, "uploadFile", "student.csv");
Any suggestions?
You could just build the CSV string and pass it to a new instance of StringContent instead of using ByteArrayContent.

Categories

Resources