Restore deleted files using Dropbox API

跟風遠走 提交于 2019-12-25 06:36:15

问题


I was searching for a way to use Dropbox API to restore my files and Google brought me here.

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. I want to download all my original files using 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.

My problem:

I used Python API wrapper to work with 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. 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

回答1:


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. 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. 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. 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. 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))

(where files is an instance of dropbox.files.ListFolderResult)

  1. Here's where things get a bit hairy when it comes to API calls. For each of the deleted files, you need to fetch a list of revisions, using dropbox.Dropbox.files_list_revisions. Take the first revision, which will be the newest, and store its ID alongside the file path. This is how we get an ID for a deleted file.
  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. 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. 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.




回答2:


Thanks James Scholes, Exactly what I was looking for. 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,




回答3:


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

}


来源:https://stackoverflow.com/questions/38912264/restore-deleted-files-using-dropbox-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!