> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 自動処理の例

> セッションを開き、バッチを作成し、銀行申込書の画像をアップロードして処理し、結果を読み取る ABBYY FlexiCapture API の例を順を追って説明します。

この例では、銀行口座開設申込書をサーバーにアップロードし、顧客データを抽出する方法を示します。

<div id="what-the-example-does">
  ## サンプルの内容
</div>

このサンプルコードでは、次の手順を実行します。

* サービスに接続します
* セッションを開始します
* プロジェクトを開きます
* 新しいバッチを作成します
* バッチに画像を追加します
* バッチの処理を開始します
* 結果を取得し、抽出されたデータを表示します
* セッションを終了します

<div id="set-up-the-example">
  ## サンプルをセットアップする
</div>

<Steps>
  <Step title="プロジェクトファイルをサーバーにアップロード">
    `UnattendedExample.fcproj` プロジェクトファイルをサーバーにアップロードします。
  </Step>

  <Step title="Visual Studio でソリューションを開く">
    Visual Studio 2013 以降で `UnattendedExample.sln` を開きます。
  </Step>
</Steps>

<div id="connect-to-the-service">
  ## サービスに接続する
</div>

```csharp theme={null}
// Webサービスクライアントのインスタンスを作成する
var service = new FlexiCapture.FlexiCaptureWebServiceSoapClient();
// ======= 基本認証 =======
// service.ClientCredentials.UserName.UserName = "username";
// service.ClientCredentials.UserName.Password = "password";
```

<div id="open-a-session">
  ## セッションを開始する
</div>

```csharp theme={null}
// 不正アクセスからバッチを保護するために、現在のユーザーを指定します
// まず、システムに認識されているユーザー名を取得します
var username = service.GetCurrentUserIdentity();
// 次に、FlexiCaptureのユーザー一覧から自分自身を検索します
var userId = service.FindUser(username.Name);
if (userId <= 0) throw new Exception("Current user not found");
// 新しい処理セッションを開きます
const int roleType = 12; //ユーザーのステーションにおけるOperatorロール
const int stationType = 10; //ユーザーのステーション
var sessionId = service.OpenSession(roleType, stationType);
if (sessionId <= 0) throw new Exception("Couldn't open the session");
```

<div id="open-the-project">
  ## プロジェクトを開く
</div>

```csharp theme={null}
// プロジェクトを取得する
var projects = service.GetProjects();
var projectGuid = "";
if (projects != null && projects.Count > 0)
{
    foreach (var project in projects)
    {
        if (project.Name != "UnattendedExample") continue;
        projectGuid = project.Guid;
        break;
    }
}
if (string.IsNullOrEmpty(projectGuid))
{
    throw new Exception("Can't find the UnattendedExample project. You must upload this project to the server to be able to work with this example.");
}
// UnattendedExampleという名前の最初のプロジェクトを開く
var projectId = service.OpenProject(sessionId, projectGuid);
if (projectId <= 0) throw new Exception("Couldn't open the project");
```

<div id="create-a-new-batch">
  ## 新しいバッチを作成する
</div>

```csharp theme={null}
// 新しいバッチの名前を指定し、他のプロパティはそのままにする
var batch = new FlexiCapture.Batch { Name = "Sample API Batch" };
var batchId = service.AddNewBatch(sessionId, projectId, batch, userId);
if (batchId <= 0) throw new Exception("Couldn't create the batch");
```

<div id="add-images-to-the-batch">
  ## バッチに画像を追加する
</div>

```csharp theme={null}
// 画像を追加するバッチを開く
service.OpenBatch(sessionId, batchId);
```

<div id="upload-files-smaller-than-256-kb">
  ### 256 KB未満のファイルをアップロードする
</div>

```csharp theme={null}
service.AddNewImage(sessionId, batchId, new FlexiCapture.File()
{
    Bytes = File.ReadAllBytes(filename),
    Name = filename
});
```

<div id="upload-larger-files">
  ### 大きなファイルをアップロードする
</div>

256 KB を超えるファイル全体を Base64 でアップロードすると、次のような欠点があります。

* ネットワーク負荷が 33% 増加する
* 非常に大きなリクエストは、IIS やファイアウォールによってブロックされる可能性がある
* 接続が切れたりネットワークエラーが発生したりした場合、ファイルを再送信する必要がある

ファイルサービス API 経由でファイルをアップロードする方が、はるかに効率的です。

```csharp theme={null}
var doc = new FlexiCapture.Document { BatchId = batchId };
var file = new FlexiCapture.File { Name = filename };
var documentId = service.AddNewDocument(sessionId, doc, file, false, 0);
UploadFile(service, sessionId, projectId, batchId, documentId, filename).Wait();
```

<div id="upload-a-file-to-the-server">
  #### ファイルをサーバーにアップロードする
</div>

`UploadFile` メソッドはファイルを読み取り、1 MB ごとにファイルサービスに送信した後、チェックサムを使用してアップロードを検証します。

```csharp theme={null}
private static async Task UploadFile(FlexiCapture.FlexiCaptureWebServiceSoapClient service, int sessionId, int projectId,
    int batchId, int documentId, string filename)
{
    const int objectType = 0;
    var crc = new Crc32();
    using (var fs = File.OpenRead(filename))
    {
        // ファイルを 1 MB ごとに分割してアップロード
        var buffer = new byte[0x100000];
        var readed = fs.Read(buffer, 0, buffer.Length);
        var checksum = crc.Next(buffer, 0, readed);
        if (readed < buffer.Length)
        {
            // 小さいファイルはまとめてアップロード
            var resp = await FileRequest(service, "Save", objectType, sessionId, projectId, batchId, 0, documentId, 0, filename, 0,
                new ByteArrayContent(buffer, 0, readed));
            if (resp.StatusCode != HttpStatusCode.OK) throw new Exception("Server error");
        }
        else
        {
            var offset = 0;
            while (readed > 0)
            {
                var action = offset == 0 ? "BeginSaveChunked" : "Append";
                await FileRequest(service, action, objectType, sessionId, projectId, batchId, 0, documentId, 0, filename,
                    offset, new ByteArrayContent(buffer, 0, readed));
                offset += readed;
                readed = fs.Read(buffer, 0, buffer.Length);
                checksum = crc.Next(buffer, 0, readed);
            }
            var resp = await FileRequest(service, "Commit", objectType, sessionId, projectId, batchId, 0, documentId, 0, filename);
            if (resp.StatusCode != HttpStatusCode.OK) throw new Exception("Server error");
        }
        var response = await FileRequest(service, "Checksum", objectType, sessionId, projectId, batchId, 0, documentId, 0, filename);
        var text = await response.Content.ReadAsStringAsync();
        if (uint.Parse(text, NumberStyles.HexNumber) != checksum)
        {
            throw new Exception("An error occurred when uploading the file");
        }
    }
}
```

<div id="send-a-file-request-with-file-content">
  #### ファイルの内容を含むファイルリクエストを送信する
</div>

`FileRequest` メソッドには、ファイルサービスにアクションを送信するためのオーバーロードが 2 つあります。1 つ目は、ファイルの内容をマルチパートフォームデータとして送信します。

```csharp theme={null}
private static async Task<HttpResponseMessage> FileRequest(FlexiCapture.FlexiCaptureWebServiceSoapClient service, string action,
    int objectType, int sessionId, int projectId, int batchId, int parentId, int objectId, int version, string streamName, int offset, HttpContent file)
{
    var creds = CredentialCache.DefaultNetworkCredentials;
    if (!string.IsNullOrEmpty(service.ClientCredentials.UserName.UserName))
        creds = new NetworkCredential(service.ClientCredentials.UserName.UserName, service.ClientCredentials.UserName.Password);
    using (var handler = new HttpClientHandler { Credentials = creds })
    using (var client = new HttpClient(handler))
    {
        var uri = service.Endpoint.Address.Uri;
        var content = new MultipartFormDataContent
        {
            {new StringContent(action), "Action"},
            {new StringContent(objectType.ToString()), "objectType"},
            {new StringContent(sessionId.ToString()), "sessionId"},
            {new StringContent(projectId.ToString()), "projectId"},
            {new StringContent(batchId.ToString()), "batchId"},
            {new StringContent(parentId.ToString()), "parentId"},
            {new StringContent(objectId.ToString()), "objectId"},
            {new StringContent(version.ToString()), "version"},
            {new StringContent(Convert.ToBase64String(Encoding.Unicode.GetBytes(streamName))), "streamName"},
        };
        if (offset > 0)
        {
            content.Add(new StringContent(offset.ToString()), "offset");
        }
        content.Add(file, "blob", "data.txt");
        return await client.PostAsync(uri.OriginalString.Replace("/API/v1/Soap", "/FileService/v1"), content);
    }
}
```

<div id="send-a-file-request-without-file-content">
  #### ファイルの内容を含めずにファイルリクエストを送信する
</div>

2つ目のオーバーロードは、フォーム URL エンコードを使用して、ファイルの内容を含まないリクエストを送信します:

```csharp theme={null}
private static async Task<HttpResponseMessage> FileRequest(FlexiCapture.FlexiCaptureWebServiceSoapClient service, string action,
    int objectType, int sessionId, int projectId, int batchId, int parentId, int objectId, int version, string streamName)
{
    var creds = CredentialCache.DefaultNetworkCredentials;
    if (!string.IsNullOrEmpty(service.ClientCredentials.UserName.UserName))
        creds = new NetworkCredential(service.ClientCredentials.UserName.UserName, service.ClientCredentials.UserName.Password);
    using (var handler = new HttpClientHandler { Credentials = creds })
    using (var client = new HttpClient(handler))
    {
        var uri = service.Endpoint.Address.Uri;
        var content = new FormUrlEncodedContent(new Dictionary<string, string>
        {
            {"Action", action},
            {"objectType", objectType.ToString()},
            {"sessionId", sessionId.ToString()},
            {"projectId", projectId.ToString()},
            {"batchId", batchId.ToString()},
            {"parentId", parentId.ToString()},
            {"objectId", objectId.ToString()},
            {"version", version.ToString()},
            {"streamName", streamName},
        });
        return await client.PostAsync(uri.OriginalString.Replace("/API/v1/Soap", "/FileService/v1"), content);
    }
}
```

<div id="start-and-end-batch-processing">
  ## バッチ処理の開始と終了
</div>

```csharp theme={null}
// バッチの処理を開始する
service.ProcessBatch(sessionId, batchId);
Console.WriteLine("recognition task created, waiting ");
// 処理が完了するまで待機する
var percentCompleted = 0;
while (percentCompleted < 100)
{
    Console.CursorLeft = 0;
    Console.Write(percentCompleted + "%");
    percentCompleted = service.GetBatchPercentCompleted(batchId);
    System.Threading.Thread.Sleep(500);
}
Console.CursorLeft = 0;
Console.WriteLine("complete...");
```

<div id="get-the-results-and-display-the-captured-data">
  ## 結果を取得して抽出されたデータを表示する
</div>

各ドキュメントで表示されるフィールドは、次の 3 つのみです。

* **宛名**
* **名**
* **姓**

```csharp theme={null}
// 結果を取得する
var documents = service.GetDocuments(sessionId, batchId);
if (documents == null) return;
// XML結果の解析に必要なXML名
var docs = XName.Get("Documents", "https://www.abbyy.com/FlexiCapture/Schemas/Export/FormData.xsd");
var banking = XName.Get("_Banking_eng", "https://www.abbyy.com/FlexiCapture/Schemas/Export/Banking_eng.xsd");
// すべての結果を反復処理して画面に表示する
foreach (var document in documents)
{
    if (document.Id == 0) continue;
    // 認識されたデータを含むXMLファイルを取得する
    var attachedFile = service.LoadDocumentResult(sessionId, batchId, document.Id, "Result.xml");
    if (attachedFile.Bytes == null) continue;
    // 結果をXMLで開く
    var xml = XDocument.Load(new MemoryStream(attachedFile.Bytes));
    var docsElement = xml.Element(docs); // 認識されたデータのコンテナー
    if (docsElement == null) continue;
    var result = docsElement.Element(banking);
    if (result == null) continue;
    // 必要なデータを取得する
    var addressing = result.Element("_Addressing");
    var surname = result.Element("_Last_Name");
    var name = result.Element("_First_Name");
    // データを表示する
    Console.WriteLine("- " +
        (addressing == null ? "" : addressing.Value) + " " +
        (name == null ? "" : name.Value) + " " +
        (surname == null ? "" : surname.Value)
    );
}
```

<div id="close-the-session">
  ## セッションの終了
</div>

```csharp theme={null}
service.DeleteBatch(sessionId, batchId);
service.CloseProject(sessionId, projectId);
service.CloseSession(sessionId);
```
