

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用自訂檔案處理步驟
<a name="custom-step-details"></a>

透過使用自訂檔案處理步驟，您可以使用 使用自有檔案處理邏輯 AWS Lambda。到達檔案時，Transfer Family 伺服器會叫用包含自訂檔案處理邏輯的 Lambda 函數，例如加密檔案、掃描惡意軟體或檢查不正確的檔案類型。在下列範例中，目標 AWS Lambda 函數用於處理上一個步驟的輸出檔案。

![\[自訂步驟畫面，並選取套用自訂處理至從上一個步驟建立的檔案選項按鈕，以及目標欄位中顯示的 Lambda 函數。\]](http://docs.aws.amazon.com/zh_tw/transfer/latest/userguide/images/workflows-step-custom.png)


**注意**  
如需 Lambda 函數的範例，請參閱[自訂工作流程步驟的範例 Lambda 函數](#example-workflow-lambda)。如需範例事件 （包括傳入 Lambda 的檔案位置），請參閱 [檔案上傳 AWS Lambda 時傳送至 的範例事件](#example-workflow-lambdas)。

使用自訂工作流程步驟時，您必須設定 Lambda 函數來呼叫 [SendWorkflowStepState](https://docs.aws.amazon.com/transfer/latest/APIReference/API_SendWorkflowStepState.html) API 操作。 會`SendWorkflowStepState`通知工作流程執行，該步驟已完成，包括成功或失敗狀態。`SendWorkflowStepState` API 操作的狀態會根據 Lambda 函數的結果，叫用線性序列中的例外處理常式步驟或名目步驟。

如果 Lambda 函數失敗或逾時，則步驟會失敗，而您會在 CloudWatch 日誌`StepErrored`中看到 。如果 Lambda 函數是名目步驟的一部分，且函數`SendWorkflowStepState`以 `Status="FAILURE"`或逾時回應 ，則流程會繼續執行例外處理常式步驟。在此情況下，工作流程不會繼續執行剩餘的 （如果有的話） 標稱步驟。如需詳細資訊，請參閱[工作流程的例外狀況處理](transfer-workflows.md#exception-workflow)。

當您呼叫 `SendWorkflowStepState` API 操作時，您必須傳送下列參數：

```
{
    "ExecutionId": "string",
    "Status": "string",
    "Token": "string",
    "WorkflowId": "string"
}
```

您可以從 Lambda `ExecutionId`函數執行時傳遞的`WorkflowId`輸入事件中擷取 `Token`、 和 （範例如下列各節所示）。`Status` 值可以是 `SUCCESS`或 `FAILURE`。

若要能夠從 Lambda 函數呼叫 `SendWorkflowStepState` API 操作，您必須使用[推出受管工作流程](doc-history.md#workflows-introduced)之後發佈的 AWS SDK 版本。

## 連續使用多個 Lambda 函數
<a name="multiple-lambdas"></a>

當您依序使用多個自訂步驟時，**檔案位置**選項的運作方式會與只使用單一自訂步驟不同。Transfer Family 不支援傳遞 Lambda 處理的檔案，以用作下一個步驟的輸入。因此，如果您有多個自訂步驟都設定為使用 `previous.file`選項，則它們都使用相同的檔案位置 （第一個自訂步驟的輸入檔案位置）。

**注意**  
如果您在自訂步驟之後有預先定義的步驟 （標籤、複製、解密或刪除），`previous.file`則設定的運作方式也不同。如果預先定義的步驟設定為使用 `previous.file`設定，預先定義的步驟會使用自訂步驟所使用的相同輸入檔案。來自自訂步驟的已處理檔案不會傳遞至預先定義的步驟。

## 在自訂處理之後存取檔案
<a name="process-uploaded-file"></a>

如果您使用 Amazon S3 做為儲存體，而且您的工作流程包含對原始上傳的檔案執行動作的自訂步驟，則後續步驟無法存取該已處理的檔案。也就是說，自訂步驟之後的任何步驟都無法參考來自自訂步驟輸出的更新檔案。

例如，假設您在工作流程中有下列三個步驟。
+ **步驟 1** – 上傳名為 的檔案`example-file.txt`。
+ **步驟 2** – 叫用`example-file.txt`以某種方式變更的 Lambda 函數。
+ **步驟 3** – 嘗試對更新版本的 執行進一步處理`example-file.txt`。

如果您將步驟 3 `sourceFileLocation`的 設定為 `${original.file}`，步驟 3 會使用在步驟 1 中將檔案上傳至儲存體時來自 的原始檔案位置。如果您使用 `${previous.file}`進行步驟 3，步驟 3 會重複使用步驟 2 用作輸入的檔案位置。

因此，步驟 3 會導致錯誤。例如，如果步驟 3 嘗試複製更新的 `example-file.txt`，您會收到下列錯誤：

```
{
    "type": "StepErrored",
    "details": {
        "errorType": "NOT_FOUND",
        "errorMessage": "ETag constraint not met (Service: null; Status Code: 412; Error Code: null; Request ID: null; S3 Extended Request ID: null; Proxy: null)",
        "stepType": "COPY",
        "stepName": "CopyFile"
    },
```

發生此錯誤是因為自訂步驟修改 的實體標籤 (ETag)，`example-file.txt`使其不符合原始檔案。

**注意**  
如果您使用 Amazon EFS，則不會發生此行為，因為 Amazon EFS 不會使用實體標籤來識別檔案。

## 檔案上傳 AWS Lambda 時傳送至 的範例事件
<a name="example-workflow-lambdas"></a>

下列範例顯示檔案上傳完成 AWS Lambda 時傳送至 的事件。其中一個範例使用 Transfer Family 伺服器，其中網域是使用 Amazon S3 設定。另一個範例使用 Transfer Family 伺服器，其中網域使用 Amazon EFS。

------
#### [ Custom step that uses an Amazon S3 domain ]

```
{
    "token": "MzI0Nzc4ZDktMGRmMi00MjFhLTgxMjUtYWZmZmRmODNkYjc0",
    "serviceMetadata": {
        "executionDetails": {
            "workflowId": "w-1234567890example",
            "executionId": "abcd1234-aa11-bb22-cc33-abcdef123456"
        },
        "transferDetails": {
            "sessionId": "36688ff5d2deda8c",
            "userName": "myuser",
            "serverId": "s-example1234567890"
        }
    },
    "fileLocation": {
        "domain": "S3",
        "bucket": "amzn-s3-demo-bucket",
        "key": "path/to/mykey",
        "eTag": "d8e8fca2dc0f896fd7cb4cb0031ba249",
        "versionId": null
    }
}
```

------
#### [ Custom step that uses an Amazon EFS domain ]

```
{
    "token": "MTg0N2Y3N2UtNWI5Ny00ZmZlLTk5YTgtZTU3YzViYjllNmZm",
    "serviceMetadata": {
        "executionDetails": {
            "workflowId": "w-1234567890example",
            "executionId": "abcd1234-aa11-bb22-cc33-abcdef123456"
        },
        "transferDetails": {
            "sessionId": "36688ff5d2deda8c",
            "userName": "myuser",
            "serverId": "s-example1234567890"
        }
    },
    "fileLocation": {
        "domain": "EFS",
        "fileSystemId": "fs-1234567",
        "path": "/path/to/myfile"
    }
}
```

------

## 自訂工作流程步驟的範例 Lambda 函數
<a name="example-workflow-lambda"></a>

下列 Lambda 函數會擷取有關執行狀態的資訊，然後呼叫 [SendWorkflowStepState](https://docs.aws.amazon.com/transfer/latest/APIReference/API_SendWorkflowStepState.html) API 操作，將狀態傳回至步驟的工作流程： `SUCCESS`或 `FAILURE`。在函數呼叫 `SendWorkflowStepState` API 操作之前，您可以設定 Lambda 根據您的工作流程邏輯採取動作。

```
import json
import boto3

transfer = boto3.client('transfer')

def lambda_handler(event, context):
    print(json.dumps(event))

    # call the SendWorkflowStepState API to notify the workflow about the step's SUCCESS or FAILURE status
    response = transfer.send_workflow_step_state(
        WorkflowId=event['serviceMetadata']['executionDetails']['workflowId'],
        ExecutionId=event['serviceMetadata']['executionDetails']['executionId'],
        Token=event['token'],
        Status='SUCCESS|FAILURE'
    )

    print(json.dumps(response))

    return {
      'statusCode': 200,
      'body': json.dumps(response)
    }
```

## 自訂步驟的 IAM 許可
<a name="custom-step-iam"></a>

若要允許呼叫 Lambda 的步驟成功，請確定工作流程的執行角色包含下列許可。

```
{
    "Sid": "Custom",
    "Effect": "Allow",
    "Action": [
        "lambda:InvokeFunction"
    ],
    "Resource": [
        "arn:aws:lambda:region:account-id:function:function-name"
    ]
}
```