使用 Dropbox 恢复删除的文件 API

Restore deleted files using Dropbox API

我正在寻找一种使用 Dropbox API 来恢复我的文件的方法,Google 把我带到了这里。

首先说一下我的情况:

我的电脑感染了病毒,它重命名了我的所有文件(如果在 Dropbox 上被识别为重命名或删除,则为 idk)并且它们都同步到 Dropbox。我想使用 Dropbox API.

下载我所有的原始文件

正如我在网络界面上看到的那样,我可以单独下载它们,但是我有上千个文件所以我无法下载。

我的问题:

我使用 Python API 包装器来处理 Dropbox API。我首先获取了我所有的文件并尝试获取他们的所有修订版,但原始文件未包含在修订版列表中。

然后我尝试列出我的所有文件,包括已删除的文件,我可以看到列出了我的原始文件。我尝试使用下载端点下载它们,但它返回 File not found 错误。有没有人碰到过类似的东西?我该如何解决这个问题?

我的代码片段:

dbx = dropbox.Dropbox('token is intentionally hidden')
print dbx.users_get_current_account()
for entry in dbx.files_list_folder('', recursive = False, include_deleted = True).entries:
  if (isinstance(entry, dropbox.files.FileMetadata) or isinstance(entry, dropbox.files.DeletedMetadata)):
    if not entry.name.endswith('cerber2'):
      print "name: ", entry.name, "| path: ", entry.path_lower 
      print repr(entry)
      try:
        meta, resp = dbx.files_download(entry.path_lower)
      except dropbox.exceptions.ApiError as e:
        print e.user_message_text
      print "-" * 80

今天下午我一直在为这个确切的问题绞尽脑汁,试图恢复一个朋友的 Dropbox 的状态,它被同样的勒索软件攻击了。我不知道你是否仍然需要解决方案,但简而言之,这是游戏状态。

在 Dropbox API V2 中,每个文件都有一个唯一的 ID。这在删除、重命名、移动等过程中持续存在。这将是解决此问题的关键,因为 Dropbox 通过文件路径跟踪文件历史记录,因此一旦勒索软件重命名了您的文件,就可以选择以编程方式简单地回滚文件丢失。使事情变得更加困难的是,获取 include_deleted 设置为 True 的目录列表,您会注意到 Dropbox 不在元数据中包含用于删除的文件 ID。如果他们这样做了,这将是一件轻而易举的事。

因此,改为执行以下操作:

  1. 正常获取文件列表。
  2. 将该文件列表分成两个列表,现有文件和已删除的文件:

    删除=列表(过滤器(lambda文件:isinstance(文件,dropbox.files.DeletedMetadata),files.entries))

(其中 filesdropbox.files.ListFolderResult 的实例)

  1. 这里是 API 调用的问题所在。对于每个已删除的文件,您需要使用 dropbox.Dropbox.files_list_revisions 获取修订列表。采用第一个修订版,这将是最新的,并将其 ID 与文件路径一起存储。这就是我们如何获得已删除文件的 ID。
  2. 现在我们(希望)为您 folder/Dropbox 中的每个已删除文件都有一个 ID,剩下要做的就是将这些 ID 与现有加密 .cerber2 文件的 ID 进行匹配。完成此操作后,您将在加密的 .cerber2 文件和存储在 Dropbox 历史记录中的原始解密文件之间建立映射。只需恢复旧文件并删除病毒创建的文件。

我特意将代码中的实际实现留给了您,但我希望这对您有所帮助。

谢谢 James Scholes,正是我要找的。 解决方案适用于文件,但不适用于文件夹,因为文件夹没有 versions/revisions。在这种情况下,我可以通过其他任何方式取消删除文件夹吗??。

谢谢,

Java中的示例代码:

    public static void main(String[] args) throws IOException, DbxException {

    String userLocale = Locale.getDefault().toString();
    DbxRequestConfig requestConfig = new DbxRequestConfig("examples-authorize", userLocale);

    DbxClientV2 client = new DbxClientV2(requestConfig, AUTH_TOKEN);
    FullAccount account = client.users().getCurrentAccount();

    Set<String> folderNames;

    SearchResult result = client.files().searchBuilder("/Pankaj", "*.cerber3").withMaxResults(1000L).withMode(SearchMode.FILENAME).start();
    folderNames = new HashSet<>(result.getMatches().size());
    for (SearchMatch match : result.getMatches()){
        FileMetadata fileMetadata = (FileMetadata) match.getMetadata();
        String path = fileMetadata.getPathLower();
        folderNames.add(path.substring(0, path.lastIndexOf("/")));
    }
    for(String path : folderNames){
        processDirectory(path, client);
    }
}

static void processDirectory(String dirName, DbxClientV2 client) throws DbxException {
    ListFolderResult result = client.files().listFolderBuilder(dirName).withIncludeDeleted(true).start();

    while (true) {
        for (Metadata metadata : result.getEntries()) {
        if(metadata instanceof DeletedMetadata){
                String filePath = metadata.getPathLower();
                if(filePath.endsWith(".doc") || filePath.endsWith(".docx") || filePath.endsWith(".pdf")){
                    List<FileMetadata> revisions = client.files().listRevisions(filePath).getEntries();
                    if(revisions.size()>0) {
                        FileMetadata revision = revisions.get(0);
                        System.out.println("Deleted File: " + filePath + ", " + revision.getClientModified() + ", Id:" + revision.getId());
                        revision.getRev();
                        client.files().restore(filePath, revision.getRev());
                    }
                }
            }
        }

        if (!result.getHasMore()) {
            break;
        }

        result = client.files().listFolderContinue(result.getCursor());
    }

}