本地计算文件的Dropbox哈希值

时间:2012-10-22 09:06:03

标签: dropbox dropbox-api

Dropbox rest api,在函数metatada中有一个名为“hash”的参数https://www.dropbox.com/developers/reference/api#metadata

我可以在不调用任何远程api休息函数的情况下在本地计算此哈希值吗?

我需要知道这个值以减少上传带宽。

5 个答案:

答案 0 :(得分:5)

元数据调用上的“hash”参数实际上不是文件的哈希值,而是元数据的哈希值。它的目的是通过在元数据请求期间提供元数据而不必更改请求中的元数据,从而节省您的时间。它不能用作文件哈希。

不幸的是,我没有看到任何通过Dropbox API来获取文件本身的哈希值。我认为减少上传带宽的最佳选择是在本地跟踪文件的哈希值,并在确定是否上传文件时检测它们是否已更改。根据您的系统,您可能还希望跟踪元数据请求中返回的“rev”(修订版)值,以便判断Dropbox上的版本是否已更改。

答案 1 :(得分:3)

https://www.dropbox.com/developers/reference/content-hash解释了Dropbox如何计算文件哈希值。这个的Python实现如下:

import hashlib
import math
import os

DROPBOX_HASH_CHUNK_SIZE = 4*1024*1024

def compute_dropbox_hash(filename):
    file_size = os.stat(filename).st_size
    num_chunks = int(math.ceil(file_size/DROPBOX_HASH_CHUNK_SIZE))

    with open(filename, 'rb') as f:
        block_hashes = b''
        while True:
            chunk = f.read(DROPBOX_HASH_CHUNK_SIZE)
            if not chunk:
                break
            block_hashes += hashlib.sha256(chunk).digest()
        return hashlib.sha256(block_hashes).hexdigest()

答案 2 :(得分:1)

这不会直接回答您的问题,但更多的是作为解决方法; dropbox sdk提供了一个简单的updown.py示例,该示例使用文件大小和修改时间来检查文件的货币。

取自updown.py的缩写示例:

dbx = dropbox.Dropbox(api_token)
...
# returns a dictionary of name: FileMetaData
listing = list_folder(dbx, folder, subfolder)
# name is the name of the file
md = listing[name]
# fullname is the path of the local file
mtime = os.path.getmtime(fullname)
mtime_dt = datetime.datetime(*time.gmtime(mtime)[:6])
size = os.path.getsize(fullname)
if (isinstance(md, dropbox.files.FileMetadata) and mtime_dt == md.client_modified and size == md.size):
    print(name, 'is already synced [stats match]')

答案 3 :(得分:0)

就我而言,不,你不能。 唯一的方法是使用Dropbox API,解释为here

答案 4 :(得分:0)

Node.js / Javascript版本

以下代码以与Dropbox相同的方式计算文件的哈希,并将其作为十六进制字符串返回。

const fs = require('fs');
const crypto = require('crypto');

function calcDropboxHash(filePath) {
  return new Promise((resolve, reject) => {
    const chunkSize = 4 * 1024 * 1024;
    const readStream = fs.createReadStream(filePath);
    const chunkHashes = [];
    readStream.on('data', data => {
      chunkHashes.push(crypto.createHash('sha256').update(data).digest());
    });
    readStream.on('error', err => {
      reject(err);
    });
    readStream.on('end', () => {
      resolve(crypto.createHash('sha256')
        .update(Buffer.concat(chunkHashes)).digest('hex'));
    });
    readStream.read(chunkSize);
  });
}