FormRecognizer C# SDK with blob file - unsupported media type error - microsoft-cognitive

I am trying to use C# FormRecognizer SDK of Azure Cognitive Service. I have pdfs stored in Azure Blob and I need to extract text/tables from these pdf files using C# SDK.
I see that "AnalyzeWithCustomModelAsync" method takes "Stream" as input parameter, where it accepts only "FileStream" type. If I pass "MemoryStream" as input parameter type, I am getting following error:
{"value":{"error":{"code":"UnsupportedMediaType","message":"In case of HTML form data, the multipart request must contain a document with a media type of - 'application/pdf', 'image/jpeg' or 'image/png'."}},"formatters":[],"contentTypes":[],"statusCode":415}
Is there anyway where I can use my blob file directly, without needing to have those files saved locally?
Regards,
Madhu

The following code snippet works by getting an instance of the blob (into CloudBlockBlob class) and then loading it into the MemoryStream. Once you have that, you can pass that into Form Recognizer to analyze.
List<string> blobsToAnalyze = new List<string>();
// Get latest Form Recognizer training model ID
Guid aiTrainModelId = Guid.Empty;
ModelResult latestModel = await FormRecognizer.GetModelAsync(config, log);
if (latestModel != null)
aiTrainModelId = latestModel.ModelId;
// Iterate through all blobs
foreach (string strBlob in blobsToAnalyze)
{
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(strBlob);
using (MemoryStream ms = new MemoryStream())
{
// Load blob into a MemoryStream object
await blob.DownloadToStreamAsync(ms);
// Send to Form Recognizer to analyze
AnalyzeResult results = await FormRecognizer.AnalyzeFormAsync(config, aiTrainModelId, ms, log);
searchResults = FormRecognizer.AnalyzeResults(config, tableClient, results, log);
}
}

Related

Error 500 when replacing file in Azure Blob Storage

Good day, I'm having an error where when I replace a file, it returns "500 internal server error". But when I upload a new file everything is okay.
Here is my code:
public async Task UploadContentBlobAsync(IFormFile formFile, string fileName)
{
var blobClient = _containerClient.GetBlobClient(fileName);
await blobClient.UploadAsync(formFile.OpenReadStream());
}
accoring to this source Azure will just replace my fie to be uploaded to the existing file, but that doesn't happen to my case.
I am using Azure.Storage.Blobs 12.4.3, I create a method and pass the request as a parameter. The following code works and no error will be reported during the replacement of blob content:
string connectionString = "DefaultEndpointsProtocol=https;AccountName=0730bowmanwindow;AccountKey=xxxxxx;EndpointSuffix=core.windows.net";
string containerName = "video";
string fileName = "1.png";
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
BlobClient blobClient = containerClient.GetBlobClient(fileName);
await blobClient.UploadAsync(req.Body, true);
(I put the picture in the binary format and put it in the request.)
In the package I use, the Boolean value of parameter of the UploadAsync method about whether to override blob is false, so I must provide a true, otherwise it will report an error.
You can make an experiment to see if it can be executed correctly according to the package version and code provided by me. If not, please provide detail error information.:)

How to read a local json file and display

newbie here,I could not find any example on Xamarin Forms read a local json file and display it. I need to do a local testing to read the local Json file.
1) Where do I save the json file for reading? in Android and iOS Projects or just in PCL project?
2) How to read the file?
here the code but it is not complete as I dont how to read the file.
using (var reader = new System.IO.StreamReader(stream))
{
var json = reader.ReadToEnd();
var rootobject = JsonConvert.DeserializeObject<Rootobject>(json);
whateverArray = rootobject.Whatever;
}
The code miss the Path and others which required.
You can directly add your JSON file in PCL. Then change build action to Embedded Resource
Now you can read Json data by:
var assembly = typeof("<ContentPageName>").GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("Your_File.json");
using (var reader = new System.IO.StreamReader(stream))
{
var json = reader.ReadToEnd();
var data= JsonConvert.DeserializeObject<Model>(json);
}

documentDB .net Rest Create Docs with auto gen id

I am trying to create a new document in documentDB via the rest API. I would use the SDK, but im running the project from asp.net core and the SDK isn't compatible yet.
I would like to have documentDB auto generate the id for the document, but I am having problems with my request.
What should I set the ids value to when creating the document via the documentDB rest api (using id based routing)?
Right now I am getting hit with the 400 bad request error.
Ive tried posting it with the following variations on the id:
No id property
id: null
id: ""
The code i am using is basically what was in the github .net rest examples, i have the replace call, get calls working fine.
Here is my code making the request:
//Create a document
verb = "POST";
resourceType = "docs";
resourceLink = string.Format("dbs/{0}/colls/{1}/docs", databaseId, collectionId);
resourceId =string.Format("dbs/{0}/colls/{1}", databaseId, collectionId);
authHeader = GenerateMasterKeyAuthorizationSignature(verb, resourceId, resourceType, masterKey, "master", "1.0");
client.DefaultRequestHeaders.Remove("authorization");
client.DefaultRequestHeaders.Add("authorization", authHeader);
string content = JsonConvert.SerializeObject(document);
StringContent contentMessage = new StringContent(content, System.Text.Encoding.UTF8, "application/json");
contentMessage.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
contentMessage.Headers.ContentType.CharSet = null;
var r = client.PostAsync(baseUri + resourceLink, contentMessage).Result;
System.Diagnostics.Debug.WriteLine(r.Content.ReadAsStringAsync().Result);
return r.Content.ReadAsStringAsync().Result;
You should supply a string value for the "id" property. The auto-id functionality (like Larry mentions) is a client-side feature, not part of the REST API. So when consuming directly from REST, you must generate a Guid (or any unique string) and set the "id" property with that value.

Is there a cross-platform solution to ImageSource to byte[]?

I did researches and fell on this solution: http://forums.xamarin.com/discussion/22682/is-there-a-way-to-turn-an-imagesource-into-a-byte-array
Initial question: http://forums.xamarin.com/discussion/29569/is-there-a-cross-platform-solution-to-imagesource-to-byte#latest
We want to upload an image through a HTTP Post, here's what we tried:
HttpClient httpClient = new HttpClient ();
byte[] TargetImageByte = **TargetImageSource**; //How to convert it to a byte[]?
HttpContent httpContent = new ByteArrayContent (TargetImageByte);
httpClient.PostAsync ("https://api.magikweb.ca/debug/file.php", httpContent);
We also are having a hard time with the libraries we gotta include in the using clauses. It seems like using System.IO; works, but it doesn't give us access to classes like FileInfo or FileStream.
Anybody has any idea how this can be done aside from custom platform-specific converters?
Possibly a Xamarin.Forms.ImageSource function toByte()?
Lemme know if you need more information.
TargetImageSource is a Xamarin.Forms.ImageSource.
ImageSource TargetImageSource = null;
Solution (Sten was right)
The ImageSource has to originate from another type to exist, that previous type can be converted to a byte[]. In this case, I use the Xamarin.Forms.Labs to take a picture and it returns a MediaFile in which a FileStream is accessible through the Source property.
//--Upload image
//Initialization
HttpClient httpClient = new HttpClient ();
MultipartFormDataContent formContent = new MultipartFormDataContent ();
//Convert the Stream into byte[]
byte[] TargetImageByte = ReadFully(mediaFile.Source);
HttpContent httpContent = new ByteArrayContent (TargetImageByte);
formContent.Add (httpContent, "image", "image.jpg");
//Send it!
await httpClient.PostAsync ("https://api.magikweb.ca/xxx.php", formContent);
App.RootPage.NavigateTo (new ClaimHistoryPage());
The function:
public static byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream()){
input.CopyTo(ms);
return ms.ToArray();
}
}
I think you're looking at it a bit backwards.
ImageSource is a way to provide a source image for Xamarin.Forms.Image to show some content. If you're already showing something on the screen your Image view was populated with data that came from elsewhere, such as a file or resource or stored in an array in memory... or however else you got that in the first place. Instead of trying to get that data back from ImageSource you can keep a reference to it and upload it as needed.
Maybe you can elaborate a bit on your particular need if you don't feel this solution applies to your case.
Pseudo code:
ShowImage(){
ImageSource imageSource = ImageSource.FromFile("image.png"); // read an image file
xf_Image.Source = imageSource; // show it in your UI
}
UploadImage(){
byte[] data = File.ReadAll("image.png");
// rather than
// byte[] data = SomeMagicalMethod(xf_Image.Source);
HttpClient.Post(url, data);
}
UPDATE:
Since you're taking a picture you can copy the MediaFile.Source stream into a memory stream, then you can reset the memory stream's position to point at the beginning of the stream so that you can read it once again and copy it to the http body.
Alternatively you can store the MediaFile.Source to a file and use ImageSource.FromFile to load it in the UI, and when necessary - you can copy the file's contents into an http post body.

ASP.NET Web API 2 file upload

I would like to know how best to handle file upload and addtional information added to the file to be uploaded using ASP.NET Web API 2 without MVC components. I have google the net and I can tell you I am more confused than I expected.
The Additional info will be stored in db and the file on the disk.
So far the Web API app I am building does not support multipart/form-data. It only supports the default media types. I know I need to create a media formatter.
Pls help.
I had wrote Javascript split File and upload to WEB API . i think you can reference my backend codes
In front-end you need using below code to upload your File
var xhr = new self.XMLHttpRequest();
xhr.open('POST', url, false);
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.send(chunk);
In backend use Request.InputStream.Read to catch your file bytes
[HttpPost]
[ValidateInput(false)]
public string fileUpload(string filename)
{
byte[] file = new byte[Request.InputStream.Length];
Request.InputStream.Read(file, 0, Convert.ToInt32(Request.InputStream.Length));
BinaryWriter binWriter = new BinaryWriter(new MemoryStream());
binWriter.Write(file);
StreamReader reader = new StreamReader(binWriter.BaseStream);
reader.BaseStream.Position = 0;
//This example is recevied text file
while ((line = reader.ReadLine()) != null)
{
};
}
You can just serialize your file data into BASE64 and send them as a string in case of multipart/from-data is not allowed for some reason.

Resources