Локально вычислить хэш файлов dropbox
Dropbox REST api, в функции metatada имеет параметр с именем "hash"https://www.dropbox.com/developers/reference/api#metadata
могу ли я вычислить этот хэш локально без вызова какой-либо удаленной функции rest api?
Мне нужно знать это значение, чтобы уменьшить пропускную способность загрузки.
4 ответов
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()
параметр "hash" в вызове метаданных на самом деле не является хэшем файла, а хэшем метаданных. Его цель-сохранить необходимость повторной загрузки метаданных в вашем запросе, если он не изменился, предоставив его во время запроса метаданных. Он не предназначен для использования в качестве хэша файла.
к сожалению, я не вижу никакого способа через API Dropbox получить хэш самого файла. Я думаю, что лучшим вариантом для уменьшения пропускной способности загрузки было бы отслеживать хэш ваших файлов локально и определить, если они изменились при определении того, следует ли их загружать. В зависимости от вашей системы вы также, вероятно, захотите отслеживать значение "rev" (revision), возвращаемое в запросе метаданных, чтобы вы могли узнать, изменилась ли сама версия на Dropbox.
Это не будет напрямую отвечать на ваш вопрос, но больше означает обходной путь; 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]')
Что касается меня, то нет, вы не можете. Единственный способ-использовать Dropbox API, который объясняется здесь.