提交迁移作业(无论是导入作业还是异步元数据读取 (AMR) 作业)后,可以使用 GetMigrationJobProgress API 跟踪其进度。 API 通过 SDK 和 REST 接口提供。
它返回一系列作业状态事件,包括:JobQueued、JobStart、JobProgress、JobError 和 JobEnd。
权限
提交迁移作业时使用基于应用程序的身份验证。 确保向应用程序授予 Sites.Read.All 权限或更高版本。
GetMigrationJobProgress 方法 (SDK)
语法
public ClientResult Site.GetMigrationJobProgress(
Guid jobId,
String nextToken
)
方法参数
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| jobId | Guid | 是 | 迁移作业的唯一标识符 |
| nextToken | 字符串 | 是 | 分页位置的标记。 对初始请求使用“0” |
对于已完成的作业,使用 nextToken 的请求是幂等的 -- 重复同一请求将始终返回相同的结果。
返回值
| 名称 | 类型 | 说明 |
|---|---|---|
| 日志 | IList | 当有新进度可用时,返回作业状态事件的集合;如果没有更新,则返回空集合。 |
| NextToken | String | 当有新进度可用时返回更新的字符串值,如果没有更新,则返回与 nextToken 参数相同的值。 |
方法用法示例
ClientResult result = context.Site.GetMigrationJobProgress(jobId, nextToken ?? "0");
context.ExecuteQuery();
IList logs = result.Value.Logs;
string newNextToken = result.Value.NextToken;
GetMigrationJobProgress REST API
HTTP 请求
GET https://{site_url}/_api/site/GetMigrationJobProgress(jobId='{jobId}',nextToken=0)
URI 参数
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| jobId | Guid | 是 | 迁移作业的唯一标识符 |
| nextToken | 字符串 | 是 | 分页位置的标记。 对初始请求使用“0” |
请求标头
| 标头 | 必需 |
|---|---|
| 授权:持有者 {token} | 是 |
| 接受:application/json;odata=verbose | 是 |
响应
HTTP 状态代码为 200 时的 JSON 对象。
当 HTTP 状态代码不是 200 时为空的 JSON 对象。
错误处理
| 状态代码 | 含义 | 操作 |
|---|---|---|
| 403 | 未经授权 (Unauthorized) | 确保应用/用户至少具有 Sites.Read.All 权限。 |
| 429 | 请求过多 (Too Many Requests) | 分析 Retry-After 标头,并在指定的延迟后重试。 |
| 500 | 内部服务器错误 (Internal Server Error) | 分析错误响应以识别内部错误。 请勿重试。 |
| 503 | 服务不可用 | 分析 Retry-After 标头,并在指定的延迟后重试。 |
| 内部错误代码 | 含义 |
|---|---|
| -2147213145 | 找不到作业 |
| -2147213146 | 作业状态过期 (有效期不到 5 天) |
API 用法示例
请求示例
GET https://contoso.sharepoint.com/_api/site/GetMigrationJobProgress(jobId=' 3e280efa-78a3-4ba1-bac6-e447aa538ca5', nextToken=0)
成功响应示例
状态代码:200 响应正文:
{
"d": {
"GetMigrationJobProgress": {
"Logs": {
"__metadata": {
"type": "Collection(Edm.String)"
},
"results": [
"{\"MigrationType\":\"None\",\"MigrationDirection\":\"Import\",\"SiteId\":\"48f1898f-77d9-4a1b-bddc-1f49bb6dc134\",\"DbId\":\"de6b85cd-726e-4b13-ae04-629798fddbf3\",\"TotalRetryCount\":\"0\",\"JobId\":\"3e280efa-78a3-4ba1-bac6-e447aa538ca5\",\"Time\":\"05/20/2025 09:18:48.132\",\"CorrelationId\":\"91884a0c-5ee8-4e1f-a23f-e4f7ec170182\",\"Event\":\"JobQueued\"}",
"{\"MigrationType\":\"None\",\"MigrationDirection\":\"Import\",\"SiteId\":\"48f1898f-77d9-4a1b-bddc-1f49bb6dc134\",\"WebId\":\"7206fc09-e4af-48b3-8730-ed7321396d7a\",\"DbId\":\"de6b85cd-726e-4b13-ae04-629798fddbf3\",\"FarmId\":\"f77d7b6c-ef43-4609-8fce-0e93142ce8a0\",\"ServerId\":\"44af885c-393b-4236-9417-bae7a9edc44e\",\"SubscriptionId\":\"82abb045-250e-4186-ba83-b9295930f272\",\"TotalRetryCount\":\"0\",\"JobId\":\"3e280efa-78a3-4ba1-bac6-e447aa538ca5\",\"Time\":\"05/20/2025 09:20:51.129\",\"CorrelationId\":\"7d3e7a8e-4445-4ce0-adb1-078e78cbf686\",\"Event\":\"JobStart\"}",
"{\"MigrationType\":\"None\",\"MigrationDirection\":\"Import\",\"TotalRetryCount\":\"0\",\"ObjectType\":\"ListItem\",\"Url\":\"\",\"Id\":\"cb471d5f-593f-4a63-b59e-8eae3e35b08a\",\"SourceListItemIntId\":\"3\",\"TargetListItemIntId\":\"3\",\"ErrorCode\":\"-2147286782\",\"ErrorType\":\"Microsoft.SharePoint.SPException\",\"Message\":\"Attempted to use an object that has ceased to exist. (Exception from HRESULT: 0x80030102 (STG_E_REVERTED)) \",\"JobId\":\"3e280efa-78a3-4ba1-bac6-e447aa538ca5\",\"Time\":\"05/20/2025 09:20:55.490\",\"CorrelationId\":\"7d3e7a8e-4445-4ce0-adb1-078e78cbf686\",\"Event\":\"JobError\"}",
"{\"MigrationType\":\"None\",\"MigrationDirection\":\"Import\",\"TotalRetryCount\":\"0\",\"FilesCreated\":\"0\",\"BytesProcessed\":\"0\",\"ObjectsProcessed\":\"4\",\"TotalExpectedSPObjects\":\"15\",\"TotalErrors\":\"3\",\"TotalWarnings\":\"0\",\"WaitTimeOnSqlThrottlingMilliseconds\":\"0\",\"TotalDurationInMs\":\"0\",\"CpuDurationInMs\":\"0\",\"SqlDurationInMs\":\"0\",\"SqlQueryCount\":\"0\",\"IsShallowCopy\":\"False\",\"CreatedOrUpdatedFileStatsBySize\":\"{}\",\"ObjectsStatsByType\":\"{\\\"SPUser\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":124,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0},\\\"SPFolder\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":153,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0},\\\"SPDocumentLibrary\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":404,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0},\\\"SPFile\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":0,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0},\\\"SPListItem\\\":{\\\"Count\\\":1,\\\"TotalTime\\\":1880,\\\"AccumulatedVersions\\\":0,\\\"ObjectsWithVersions\\\":0}}\",\"TotalExpectedBytes\":\"0\",\"FilesCreatedIrrespectiveOfVersions\":\"0\",\"BytesProcessedOnlyCurrentVersion\":\"0\",\"JobId\":\"3e280efa-78a3-4ba1-bac6-e447aa538ca5\",\"Time\":\"05/20/2025 09:20:57.380\",\"CorrelationId\":\"7d3e7a8e-4445-4ce0-adb1-078e78cbf686\",\"Event\":\"JobEnd\"}"
]
},
"NextToken": "1764",
"__metadata": {
"type": "SP.MigrationJobProgress"
}
}
}
}
错误响应示例
状态代码:500 响应正文:
{
"error": {
"code": "-2147213145, Microsoft.SharePoint.SPException",
"innererror": {
"message": "Job not found",
"stacktrace": "STACK_TRACE"
},
"message": {
"lang": "en-US",
"value": "Job not found"
}
}
}
最佳做法
以 nextToken=0开头,存储返回的令牌,并按照特定间隔轮询。 此方法非常适合长时间运行的作业,有助于确保不会错过任何更新。
由于迁移作业通常需要几分钟或更长的时间,因此建议每分钟轮询一次,同时遵循 准则 以避免限制。