【问题标题】:Restore deleted files using Dropbox API使用 Dropbox API 恢复已删除的文件
【发布时间】:2016-08-12 07:26:44
【问题描述】:

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

首先说一下我的情况:

我的计算机感染了病毒,它重命名了我的所有文件(如果在 Dropbox 上识别为重命名或删除,则为 idk),并且它们都已同步到 Dropbox。我想使用 Dropbox API 下载我所有的原始文件。

正如我在网络界面上看到的,我可以单独下载它们,但我有几千个文件,所以我做不到。

我的问题:

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

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

我的代码 sn-p:

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

【问题讨论】:

  • [交叉链接供参考:dropboxforum.com/hc/en-us/community/posts/… ] 首先,您可以发布您遇到的完整错误吗?此外,乍一看,您对files_restore 的调用看起来是错误的,因为该方法需要两个参数,而您只传入一个。
  • 对不起,我粘贴了错误的代码,我刚刚更新了我的帖子,我实际上使用了 files_download() 而不是 files_restore()
  • 我实际上得到了ApiError 异常,我希望能够下载已删除的文件,因为我可以在 Dropbox 网络界面上这样做。
  • 你能打印e吗?应该有一个更有用的错误。另外,我不确定您为什么要调用files_download 两次,但如果您尝试下载文件的较旧(未删除)版本,则需要指定rev,例如,如由files_list_revisions返回。
  • 我也是这么认为的,因为我的原始文件出现在 Dropbox 网络界面的早期版本部分中,但是当我尝试调用 files_list_revisions 时,它们没有列出。它们仅在我指定include_deleted = True 时显示。我的意思是只有 1 次下载,我只是编辑了我的帖子。没有有用的错误信息,当我抓到 HTTP 包时,服务器响应 409“找不到文件”。

标签: python dropbox dropbox-api


【解决方案1】:

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

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

所以,下面是替代方法:

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

    deleted = list(filter(lambda file: isinstance(file, dropbox.files.DeletedMetadata), files.entries))

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

  1. 在涉及 API 调用时,事情变得有点棘手。对于每个已删除的文件,您需要使用dropbox.Dropbox.files_list_revisions 获取修订列表。获取第一个修订版,这将是最新的,并将其 ID 存储在文件路径旁边。这就是我们获取已删除文件 ID 的方式。
  2. 现在我们(希望)为您的文件夹/Dropbox 中的每个已删除文件都有一个 ID,剩下要做的就是将这些 ID 与现有的加密 .cerber2 文件的 ID 进行匹配。完成此操作后,您将拥有加密的 .cerber2 文件和存储在 Dropbox 历史记录中的原始解密文件之间的映射。只需恢复旧文件并删除病毒创建的文件即可。

我故意将代码中的实际实现留给你,但我希望这会有所帮助。

【讨论】:

  • 嗯,我想这有点棘手。谢谢您的回答。不过我认为 Dropbox API 应该改进以使其更易于使用。
  • revisions = dbx.files_list_revisions(entry.path_lower) 其中 entry 是已删除的文件。我得到了空的修订。我做错了吗?
【解决方案2】:

感谢詹姆斯斯科尔斯,正是我想要的。 解决方案对文件非常有效,但这不适用于文件夹,因为文件夹没有版本/修订。在这种情况下,我可以通过其他方式取消删除文件夹吗??

谢谢,

【讨论】:

    【解决方案3】:

    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());
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-09
      • 2013-06-27
      • 2014-06-11
      • 1970-01-01
      • 2012-02-11
      • 2011-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多