简体   繁体   English

使用Dropbox API还原已删除的文件

[英]Restore deleted files using Dropbox API

I was searching for a way to use Dropbox API to restore my files and Google brought me here. 我在寻找一种使用Dropbox API还原文件的方法,而Google将我带到了这里。

First of all, a bit about my situation: 首先,关于我的情况:

My computer got a virus that rename all of my files (idk if its recognized as rename or delete on Dropbox) and they are all synced to Dropbox. 我的计算机感染了一种病毒,该病毒会重命名我的所有文件(如果在idbox上被识别为重命名或删除,则为idk),并且它们都已同步到Dropbox。 I want to download all my original files using Dropbox API. 我想使用Dropbox API下载所有原始文件。

As i can see on web interface, I can download them individually but I got like thousand files so I couldn't do it. 正如我在Web界面上看到的那样,我可以单独下载它们,但由于有数千个文件,因此无法执行。

My problem: 我的问题:

I used Python API wrapper to work with Dropbox API. 我使用Python API包装器来处理Dropbox API。 I first fetched all of my files and tried to get all of their revisions but the original files are not included in revision list. 我首先获取了所有文件,并尝试获取所有版本,但原始文件未包含在版本列表中。

Then I tried to list all of my files including deleted files and I can see my original files listed. 然后,我尝试列出所有文件,包括已删除的文件,并且可以看到列出的原始文件。 I tried to download them using download endpoint but it returned File not found error. 我尝试使用下载端点下载它们,但返回“ File not found错误。 Has anyone bumped into something similar? 有没有人碰到类似的东西? How can I solve this issue? 我该如何解决这个问题?

My code snippet: 我的代码段:

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

I've been scratching my head over this exact problem this afternoon, to try and restore the state of a friend's Dropbox which got hit by the same ransomware. 今天下午,我一直在努力解决这个确切的问题,试图恢复被相同勒索软件攻击的朋友的Dropbox的状态。 I don't know whether you're still in need of a solution, but in a nutshell, here's the state of play. 我不知道您是否仍需要解决方案,但总的来说,这是一种状态。

In Dropbox API V2, every file has a unique ID. 在Dropbox API V2中,每个文件都有唯一的ID。 This is persisted across deletes, renames, moves, etc. This will be key to fixing this problem, as Dropbox tracks file history by file path, so as soon as the ransomware renamed your files, the option of simply rolling back your files programmatically was lost. 这在删除,重命名,移动等操作中保持不变。这是解决此问题的关键,因为Dropbox会按文件路径跟踪文件历史记录,因此,勒索软件重命名文件后,可以选择以编程方式简单地回滚文件丢失。 To make things even more difficult, fetch a directory listing with include_deleted set to True and you'll notice that Dropbox don't include file IDs in the metadata for deletions. 使事情变得更加困难的是,获取一个include_deleted设置为True的目录列表,您会注意到Dropbox在元数据删除中不包含文件ID。 If they did, this would be a breeze. 如果他们这样做,那将是一件轻而易举的事。

So, here's what to do instead: 因此,这是替代方法:

  1. Fetch a list of files, as normal. 照常获取文件列表。
  2. Split that list of files into two lists, existing files and those that have been deleted: 将该文件列表分为两个列表:现有文件和已删除文件:

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

(where files is an instance of dropbox.files.ListFolderResult ) (其中filesdropbox.files.ListFolderResult的实例)

  1. Here's where things get a bit hairy when it comes to API calls. 在这里,API调用变得有些繁琐。 For each of the deleted files, you need to fetch a list of revisions, using dropbox.Dropbox.files_list_revisions . 对于每个已删除的文件,您需要使用dropbox.Dropbox.files_list_revisions来获取修订列表。 Take the first revision, which will be the newest, and store its ID alongside the file path. 进行第一个修订,它将是最新的,并将其ID存储在文件路径旁边。 This is how we get an ID for a deleted file. 这就是我们获取已删除文件的ID的方式。
  2. Now that we (hopefully) have an ID for each deleted file in your folder/Dropbox, all that's left to do is to match up those IDs with the IDs of the existing encrypted .cerber2 files. 现在,我们(希望有一个)文件夹/ Dropbox中每个已删除文件的ID,剩下要做的就是将这些ID与现有加密的.cerber2文件的ID进行匹配。 Once you've done that, you'll have a mapping between the encrypted .cerber2 file and the original, decrypted file stored in your Dropbox history. 完成此操作后,您将在加密的.cerber2文件与存储在Dropbox历史记录中的原始解密文件之间建立映射。 Simply restore the old file and delete the files created by the virus. 只需还原旧文件并删除由病毒创建的文件。

I've purposefully left the actual implementation in code up to you, but I hope this helps. 我故意将代码的实际实现留给您,但我希望这会有所帮助。

Thanks James Scholes, Exactly what I was looking for. 谢谢James Scholes,正是我想要的东西。 Solution works very well with the files, but this does not work for folders, Since there is no versions/revisions for a folder. 解决方案对于文件非常有效,但是不适用于文件夹,因为没有文件夹的版本/修订版。 In this case any other way that I can undelete the folder??. 在这种情况下,可以取消删除文件夹的任何其他方式?

Thanks, 谢谢,

Sample code in Java: 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());
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM