跳到主要内容

SyncFolderPullCommand

SyncFolderPullCommand 是一个高级命令,旨在将 DID Space 中的远程目录同步到本地文件夹。它会智能地比较远程源和本地目标之间的文件,仅下载新的或已更新的文件。这能有效地确保您的本地目录是远程数据的最新镜像。

此命令与 SyncFolderPushCommand 相对应,后者用于将本地更改上传到远程目录。

用例

此命令非常适用于需要从用户的 Space 中检索文件集合的场景。常见用例包括:

  • 将用户的相册下载到本地应用程序。
  • 将应用程序数据的备份从 Space 恢复到本地计算机。
  • 保持本地工作区与存储在 Space 中的主版本同步。

输入参数

该命令的构造函数接受一个包含以下字段的对象:

  • source string (required) — 要从中拉取文件的 DID Space 中的源目录路径。该路径应以“/”结尾。
  • target string (required) — 文件将下载到您的本地文件系统中的目标路径。如果该目录不存在,命令将自动创建它。
  • concurrency number (default: 4) — 并行下载的文件数量。对于包含许多小文件的目录,增加此值可以加快处理速度。最大值受可用 CPU 核心数的限制。
  • retryCount number (default: 3) — 在将特定文件标记为错误之前,重试失败下载的次数。最大值为 10。
  • filter (object: Object) => boolean — 为每个远程对象调用的函数。返回 true 以将对象包含在同步过程中,或返回 false 以跳过它。这对于根据文件属性(如名称或大小)选择性下载文件非常有用。
  • onProgress (params: OnProgressInput) => void — 每个文件开始下载过程时触发的回调函数。它会接收一个包含当前进度的对象。
    • completed number — 已开始下载的文件数量。
    • total number — 要下载的文件总数。
    • key string — 当前正在处理的文件的键(相对路径)。
  • onAfterUpload (params: OnAfterUploadInput) => void — 每个文件成功下载后触发的回调函数。注意:尽管名称为“onAfterUpload”,但对于拉取命令,它表示下载完成。
    • completed number — 到目前为止已成功下载的文件数量。
    • total number — 要下载的文件总数。
    • key string — 刚刚完成下载的文件的键(相对路径)。
  • debug boolean (default: false) — 设置为 true 以在控制台中启用详细日志记录,这有助于调试同步过程。
  • strictSync boolean (default: false) — 此参数对 SyncFolderPullCommand 无效。该命令被设计为对本地目录非破坏性的,不会删除远程源中不存在的本地文件。

输出

spaceClient.send() 方法返回一个 promise,该 promise 会解析为一个包含操作结果的对象。

  • statusCode number — 表示请求的结果。值为 200 表示整个同步操作成功完成。
  • data object — 包含同步操作摘要的对象。
    • count number — 计划下载的文件总数。
    • errorCount number — 在所有重试后下载失败的文件数量。
    • size number — 所有成功下载文件的总大小(以字节为单位)。
    • duration number — 操作所花费的总时间(以秒为单位)。
  • statusMessage string — 如果整个命令执行失败(例如,由于身份验证问题),则会显示错误消息。
  • stack string — 如果发生不可恢复的错误,则为堆栈跟踪。

示例

以下是如何使用 SyncFolderPullCommand 将远程目录下载到本地文件夹并跟踪其进度。

示例

typescript
import { SpaceClient, SyncFolderPullCommand } from '@blocklet/did-space-js';
import getWallet from '@blocklet/sdk/lib/wallet';
import { ensureDirSync, removeSync } from 'fs-extra';
import path from 'path';

const main = async () => {
  // 1. 初始化 SpaceClient
  const wallet = getWallet();
  const spaceClient = new SpaceClient({
    endpoint: 'https://www.didspaces.com/app/api/space/...',
    wallet,
  });

  // 2. 准备用于下载的本地目录
  const localTarget = path.join(__dirname, 'my-pulled-assets');
  removeSync(localTarget); // 为此示例清理之前的运行
  ensureDirSync(localTarget);
  console.log(`Downloading files to: ${localTarget}`);

  // 3. 创建并发送命令
  const command = new SyncFolderPullCommand({
    source: '/shared-media/', // 要从中拉取的 Space 中的目录
    target: localTarget, // 要下载到的本地目录
    onProgress: ({ completed, total, key }) => {
      const progress = total > 0 ? ((completed / total) * 100).toFixed(2) : 0;
      console.log(`Progress: ${progress}% (${completed}/${total}) - Starting download for: ${key}`);
    },
  });

  const output = await spaceClient.send(command);

  // 4. 处理输出
  if (output.statusCode === 200) {
    console.log('\nFolder pull completed successfully!');
    console.log(`Total files synchronized: ${output.data.count}`);
    console.log(`Total size: ${(output.data.size / 1024).toFixed(2)} KB`);
    console.log(`Duration: ${output.data.duration.toFixed(2)}s`);
    console.log(`Errors: ${output.data.errorCount}`);
  } else {
    console.error(`Folder pull failed with status ${output.statusCode}:`, output.statusMessage);
  }
};

main().catch(console.error);

示例响应(成功)

响应

json
{
  "statusCode": 200,
  "data": {
    "errorCount": 0,
    "count": 15,
    "duration": 5.432,
    "size": 2048576
  }
}

最佳实践

筛选文件

为节省带宽和时间,请使用 filter 函数仅下载您需要的文件。例如,仅下载 JPEG 和 PNG 图片:

筛选示例

javascript
const command = new SyncFolderPullCommand({
  source: '/photos/',
  target: './downloaded_images',
  filter: (object) => {
    // 跳过目录和非图像文件
    if (object.isDir) return false;
    const lowerCaseKey = object.key.toLowerCase();
    return lowerCaseKey.endsWith('.jpg') || lowerCaseKey.endsWith('.png');
  },
});

理解同步逻辑

SyncFolderPullCommand 执行安全的单向同步。它根据文件大小和最后修改时间来比较文件。如果远程文件比其本地对应文件更新或大小不同,则会下载该文件。如果文件存在于远程但本地不存在,则会在本地创建该文件。至关重要的是,此命令不会删除任何本地文件,即使它们在远程源目录中不存在。这使其成为一种保持本地文件夹更新的非破坏性方式。