Azure API 调用在控制台应用中工作,而不是在 MVC 中工作



>我有一个 asp.net MVC应用程序,允许用户将PDF/图像上传到系统上。然后,我想将此 PDF 发送到 Azure 读取 API,并将返回的文本存储在系统上的 .text 文件中(以便稍后可以将一些数据输入数据库(。

在控制台应用程序中测试它时,我让它完美运行,尽管当我尝试将其实现到我的 MVC Web 应用程序中时,我无法让它工作; 当我上传 PDF 时,文件被上传,尽管没有其他事情发生,即没有使用返回的数据创建文本文件。当我在控制台应用程序中使用相同的 Azure API 方法尝试此操作时,它工作正常(文件是使用返回的文本创建的(

我的控制器:

public ActionResult Upload()
{
return View();
}
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
string filename = Guid.NewGuid() + Path.GetExtension(file.FileName);
string filepath = @"C:Users35385sourcereposBookingSystemBookingSystemSurveys" + filename;
file.SaveAs(Path.Combine(Server.MapPath("/Surveys"), filename));
AzureVisionAPI.ExtractToTextFile(filepath);

return View();
}

我的 Azure API 调用帮助程序方法:

namespace BookingSystem.Helpers
{
static class AzureVisionAPI
{
static string subscriptionKey = ("SUBSCRIPTON_KEY");
static string endpoint = ("END_POINT");
public static ComputerVisionClient Authenticate(string endpoint, string key)
{
ComputerVisionClient client =
new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
{ Endpoint = endpoint };
return client;
}

public static void ExtractToTextFile(string filename)
{
ComputerVisionClient client = Authenticate(endpoint, subscriptionKey);
ExtractTextLocal(client, filename).Wait();
}
public static async Task ExtractTextLocal(ComputerVisionClient client, string localImage)
{
// Helps calucalte starting index to retrieve operation ID
const int numberOfCharsInOperationId = 36;
using (Stream imageStream = File.OpenRead(localImage))
{
// Read the text from the local image
BatchReadFileInStreamHeaders localFileTextHeaders = await client.BatchReadFileInStreamAsync(imageStream);
// Get the operation location (operation ID)
string operationLocation = localFileTextHeaders.OperationLocation;
// Retrieve the URI where the recognized text will be stored from the Operation-Location header.
string operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);
// Extract text, wait for it to complete.
int i = 0;
int maxRetries = 10;
ReadOperationResult results;
do
{
results = await client.GetReadOperationResultAsync(operationId);
await Task.Delay(1000);
if (maxRetries == 9)
{
throw new Exception("Azure API timed out");
}
}
while ((results.Status == TextOperationStatusCodes.Running ||
results.Status == TextOperationStatusCodes.NotStarted) && i++ < maxRetries);
// Display the found text.
var textRecognitionLocalFileResults = results.RecognitionResults;
foreach (TextRecognitionResult recResult in textRecognitionLocalFileResults)
{
using (StreamWriter sw = new StreamWriter(@"C:Users35385sourcereposBookingSystemBookingSystemsurveytest.txt"))
{
foreach (Line line in recResult.Lines)
{
sw.WriteLine(line.Text);
}
}
}
}
}
}
}

您可能会在此处看到异步死锁。您应该等待从异步方法返回Task,而不是使用.Wait()

发生的情况是在方法返回的第一个await,然后调用.Wait()的方法,这会阻止线程并具有对当前SynchronizationContext的独占访问权限,当内部等待的事情完成时,以下代码在同一SynchronizationContext上排队,该被阻止。.Wait()永远不会停止阻塞,因为Task永远无法完成。这称为异步死锁。

这里处理它的最佳方法是使您的控制器异步并返回Task<ActionResult>,然后从上到下使用 async/await。处理此问题的另一种方法是将.ConfigureAwait(false)分散到您await的所有Task,但是在处理异步工作时最好不要阻塞。

您的代码可能如下所示:

控制器:

public ActionResult Upload()
{
return View();
}
[HttpPost]
public async Task<ActionResult> Upload(HttpPostedFileBase file)
{
string filename = Guid.NewGuid() + Path.GetExtension(file.FileName);
string filepath = @"C:Users35385sourcereposBookingSystemBookingSystemSurveys" + filename;
file.SaveAs(Path.Combine(Server.MapPath("/Surveys"), filename));
await AzureVisionAPI.ExtractToTextFile(filepath);

return View();
}

AzureVisionAPI:

namespace BookingSystem.Helpers
{
static class AzureVisionAPI
{
static string subscriptionKey = ("SUBSCRIPTON_KEY");
static string endpoint = ("END_POINT");
public static ComputerVisionClient Authenticate(string endpoint, string key)
{
ComputerVisionClient client =
new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
{ Endpoint = endpoint };
return client;
}

public static async Task ExtractToTextFile(string filename)
{
ComputerVisionClient client = Authenticate(endpoint, subscriptionKey);
await ExtractTextLocal(client, filename);
}
public static async Task ExtractTextLocal(ComputerVisionClient client, string localImage)
{
// Helps calucalte starting index to retrieve operation ID
const int numberOfCharsInOperationId = 36;
using (Stream imageStream = File.OpenRead(localImage))
{
// Read the text from the local image
BatchReadFileInStreamHeaders localFileTextHeaders = await client.BatchReadFileInStreamAsync(imageStream);
// Get the operation location (operation ID)
string operationLocation = localFileTextHeaders.OperationLocation;
// Retrieve the URI where the recognized text will be stored from the Operation-Location header.
string operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);
// Extract text, wait for it to complete.
int i = 0;
int maxRetries = 10;
ReadOperationResult results;
do
{
results = await client.GetReadOperationResultAsync(operationId);
await Task.Delay(1000);
if (maxRetries == 9)
{
throw new Exception("Azure API timed out");
}
}
while ((results.Status == TextOperationStatusCodes.Running ||
results.Status == TextOperationStatusCodes.NotStarted) && i++ < maxRetries);
// Display the found text.
var textRecognitionLocalFileResults = results.RecognitionResults;
foreach (TextRecognitionResult recResult in textRecognitionLocalFileResults)
{
using (StreamWriter sw = new StreamWriter(@"C:Users35385sourcereposBookingSystemBookingSystemsurveytest.txt"))
{
foreach (Line line in recResult.Lines)
{
sw.WriteLine(line.Text);
}
}
}
}
}
}
}

相关内容

  • 没有找到相关文章

最新更新