HL7中国批量数据导出服务实施指南
2026.01.23 - release

HL7中国批量数据导出服务实施指南 - Local Development build (v2026.01.23) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions

## ITS-BULK-003 批量数据导出状态获取

### 概述

本交易由`批量数据服务提供商`和`批量数据服务客户端`角色使用，用于获取批量数据的导出状态。

在批量数据导出操作开始后，客户端可以向响应头部字段`Content-Location`中提供的URL轮询以获取导出状态，参见FHIR 异步请求模式。

客户端在轮询导出状态时应采取指数退避策略。服务器应提供一个响应头部字段`Retry-After`，用于指示客户端在多长时间后可以再次发送请求。其中延迟时间以秒为单位，例如：`120`表示两分钟。还可以指定一个HTTP时间（例如`Fri, 31 Dec 1999 23:59:59 GMT`），表示在此时间点之前不要重试。客户端应利用这些信息来控制下次轮询请求的时间。

服务器应记录从某客户端收到的状态查询，如果客户端轮询过频繁，服务器应回复状态码`429 Too Many Requests`，除响应头部字段`Retry-After`外，还应提供带有详细说明的`OperationOutcome`资源。

客户端在发出获取导出状态请求时，应使用请求头部字段`Accept`，指明应返回`application/json`类型的响应消息。如果服务器因错误导致导出失败，应以JSON格式的`OperationOutcome`资源响应。

#### 服务端点

    GET [polling content location]

#### 响应消息

根据发出状态请求时的服务器运行状态，返回不同的导出状态信息：

- In-Progress

  表示服务器正在处理导出请求。

  - 当导出请求未提供`separate-export-status`参数，仅返回HTTP状态码`202 Accepted`。
  - 当导出请求提供了`separate-export-status`参数，并且服务器支持时，应返回两个状态：HTTP状态码`200 OK`和响应头部字段`X-Export-Status`，值为`202 Accepted`。
  - 响应头部字段`X-Progress`，可选，小于100字符的导出状态描述。该描述的格式由服务器自行决定，可以是百分比完成值（`50% complete`），也可以是更通用的状态（`in progress`）。

- Error

  表示服务器处理导出请求已经失败。

  - 当导出请求未提供`separate-export-status`参数，仅返回HTTP状态码`4XX`或`5XX`。
  - 当导出请求提供了`separate-export-status`参数，并且服务器支持时，应返回两个状态：HTTP状态码`200 OK`和响应头部字段`X-Export-Status`，值为`4XX`或`5XX`。
  - 响应头部字段`Content-Type`为`application/fhir+json`。
  - 响应消息体应为JSON格式的`OperationOutcome`资源。但是，如果无法做到（例如，返回错误的基础设施层不了解 FHIR），服务器可以其他格式返回错误消息，并在响应头部字段`Content-Type`中包含对应的值。

  如果轮询失败不是指代导出作业失败，服务器应设置`OperationOutcome.issue.code`取值为`transient@IssueType`(https://www.hl7.org/fhir/codesystem-issue-type.html#issue-type-transient)，提示客户端在后续时间重试请求。

  > 🎯 注意 ：即使部分请求的资源无法成功导出，整体导出作仍有可能完成。在这种情况下，响应消息体的`Response.error`数组应指向包含一个或多个`OperationOutcome`资源的NDJSON格式文件，以表明出错原因。部分成功时，服务器应使用状态码`200 OK`代替`4XX`或`5XX`。如何确定导出作业完全失败（错误状态）还是部分失败（完成状态）由服务器实现者决定。

- Complete

  服务器处理导出请求已经完成。

  - HTTP状态码为`200 OK`。
  - 当导出请求提供了`separate-export-status`参数，且服务器支持时，响应头部字段`X-Export-Status`取值应为`200 OK`。
  - 响应头部字段`Content-Type`为`application/json`。
  - 服务器宜返回响应头部字段`Expires`，表明导出文件清单中的文件的有效期。
  - 响应消息体记录的导出文件清单格式参见下面章节。

#### 响应消息 - 导出文件清单

导出文件清单是一个JSON对象，提供了元数据和生成的批量数据文件访问地址。客户端应可以通过这些地址访问到导出文件。这些URL可以由FHIR服务器以外的文件服务器提供。

- `transactionTime`

  必选，instant类型。表示获取时服务器的时间。导出文件清单应包含截至到该时间的任何匹配资源。不应包含该时间之后的任何资源。

  > 🎯 注意：为了满足这些限制，服务器可能需要等待数据库中所有待处理事务解决后，才开始导出流程。

- `request`

  必选，String类型。表示初始批量数据导出请求的完整网址。

  对于POST请求，该URL不会包含请求参数。

- `output`

  必选，JSON Array类型。

  一个文件数组，每个生成文件对应一个条目。如果批量数据导出请求没有返回任何资源，服务器应返回一个空数组。

  每个条目（代表一个导出文件）中的`url`字段应被填充。

  当批量数据导出请求时未携带`organizedOutputBy`参数时，每个条目的`type`字段应被填充；当批量数据导出请求携带`organizedOutputBy`参数时，`type`字段不应被填充。

  当批量数据导出请求携带`organizedOutputBy`参数，且与此类资源相关的资源继续到下一个导出文件时，`continuesInFile`字段应填充，指向下一个导出文件。

  - type - 文件中包含的FHIR资源类型。
  - url - 文件的绝对路径。文件格式应反映批量数据导出请求时`_outputFormat`参数中的请求内容。
  - continuesInFile(可选) - 当`organizedOutputBy`参数中指定FHIR资源相关的资源过多，进入下一个导出文件时，指向下一个导出文件。
  - count(可选) - 当前文件中的资源数量，以JSON数字表示。

- `deleted`

  可选，JSON Array类型。

  一组已删除的文件数组，结构与`output`数组相同。

  在服务器已经导出的数据被删除后，希望下游系统也应同步移除时非常重要。

  当批量数据导出请求中提供了`_since`时间戳，该数组应填充事务Bundle资源的导出文件，这些文件表明哪些资源符合导出请求条件，但在`_since`日期后已被删除。

  如果服务器没有资源被删除，或者未提供`_since`参数，或者因其他原因避免暴露这些数据，服务器可以省略该字段，或者返回空数组。

  出现在导出文件清单`deleted`部分的资源，不应出现在`output`部分。

  输出文件中的每一行都包含一个类型为`transaction`的`Bundle`资源，包含一个或多个表示已删除资源的条目。在每个条目中，`request.url`和`request.method`元素必须被填充。`request.method`元素应设置为`DELETE`。

  示例为`deleted`资源包（表现为导出文件中的一行）：

      {
        "resourceType": "Bundle",
        "id": "bundle-transaction",
        "meta": {"lastUpdated": "2020-04-27T02:56:00Z"},
        "type": "transaction",
        "entry":[{
          "request": {"method": "DELETE", "url": "Patient/123"}
          ...
        }]
      }

- `error`

  必选，JSON Array类型。

  消息文件数组，结构与`output`数组相同。

  与导出操作相关的error、warning和info消息应放在这里（不在`output`中）。如果没有相关消息，服务器应返回一个空数组。

  目前仅支持`OperationOutcome`资源类型，因此服务器应生成与批量数据导出文件相同格式的文件，包含`OperationOutcome`资源。

  如果请求包含无效或不支持的参数，并且带有头部字段`Prefer: handling=lenient`，且服务器能处理，应为每个参数包含一个`OperationOutcome`资源。

- `outputOrganizedBy`

  可选，String类型。

  当批量数据导出请求携带`organizeOutputBy`参数时必选，且该值与导出请求的`organizeOutputBy`参数相同。

#### 示例

导出请求未携带`organizeOutputBy`参数：

    {
        "transactionTime": "2021-01-01T00:00:00Z",
        "request" : "https://example.com/fhir/Patient/$export?_type=Patient,Observation",
        "output" : [{
          "type" : "Patient",
          "url" : "https://example.com/output/patient_file_1.ndjson"
        },{
          "type" : "Observation",
          "url" : "https://example.com/output/observation_file_1.ndjson"
        },{
          "type" : "Observation",
          "url" : "https://example.com/output/observation_file_2.ndjson"
        }],
        "deleted": [{
          "type" : "Bundle",
          "url" : "https://example.com/output/del_file_1.ndjson"
        }],
        "error" : [{
          "type" : "OperationOutcome",
          "url" : "https://example.com/output/err_file_1.ndjson"
        }]
      }

导出请求携带`organizeOutputBy`参数，值为`Patient`时：

     {
        "transactionTime": "2021-01-01T00:00:00Z",
        "request" : "https://example.com/fhir/Patient/$export?_type=Patient,Observation",
        "outputOrganizedBy": "Patient",
        "output" : [{
          "url" : "https://example.com/output/file_1.ndjson"
        },{
          "url" : "https://example.com/output/file_2.ndjson",
        },{
          "url" : "https://example.com/output/file_3.ndjson"
        }],
        "deleted": [{
          "type" : "Bundle",
          "url" : "https://example.com/output/del_file_1.ndjson"
        }],
        "error" : [{
          "type" : "OperationOutcome",
          "url" : "https://example.com/output/err_file_1.ndjson"
        }]
      }