在对数据库进行审核时,我发现一些附件内容与文档_attachments
映射中给出的哈希值不匹配。
我通过下载文档并计算其哈希值来测试这一点。将其与 Couchdb 进行比较表明它们不匹配。然后我注意到不匹配的附件是 Couchdb 配置为压缩的附件。看来我的 Couch ID 配置为使用 snappy 压缩:
foobox# grep -E 'file_compression|compressible_types' /etc/couchdb/{default,local}.ini
/etc/couchdb/default.ini:file_compression = snappy
/etc/couchdb/default.ini:compressible_types = text/*, application/javascript, application/json, application/xml
但是,当我尝试使用以下方法压缩附件内容时活泼,并计算压缩数据的哈希值,它仍然与couchdb哈希不匹配。在下面的例子中,document-25977
是未压缩的(类型application / pdf),未压缩的哈希值与couchdb提供的哈希值匹配。第二个,,document-78608
是可压缩类型(text / plain),哈希值不匹配:
foobox$ python hashcompare.py
document-25977
couch len: 142918
couch hash: 028540dd92e1982bcb65c29d32e9617e (md5)
local uncompressed len: 142918
local uncompressed hash: 028540dd92e1982bcb65c29d32e9617e
local compressed len: 132333
local compressed hash: 3157583223dc1a53e1a3386d6abc312d
document-78608
couch len: 2180
couch hash: e613ab6d7f884b835142979489170499 (md5)
local uncompressed len: 2180
local uncompressed hash: 0ab2516c820f5d7afb208e3be7b924dd
local compressed len: 1382
local compressed hash: d9e79232662f57e6af262fc9f867eaf2
这是我用来进行比较的脚本:
import couchdb
import snappy
import md5
import base64
server = couchdb.Server('http://localhost:9999')
db = server['program1']
for doc_id in ['document-25977', 'document-78608']:
print doc_id
doc = db[doc_id]
att_stub = doc['_attachments'][doc_id]
hash_type, tmpdigest = att_stub['digest'].split('-', 1)
att = db.get_attachment(doc, doc_id)
data = att.read()
# CouchDB is using snappy compression
compressed_data = snappy.compress(data)
print 'couch len: ', att_stub['length']
print 'couch hash: ', base64.b64decode(tmpdigest).encode('hex'), '(%s)' % hash_type
print 'local uncompressed len: ', len(data)
print 'local uncompressed hash: ', md5.md5(data).digest().encode('hex')
print 'local compressed len: ', len(compressed_data)
print 'local compressed hash: ', md5.md5(compressed_data).digest().encode('hex')
print
我已经验证了获取的文档没有损坏。那么我遗漏了什么?我对 Erlang 不够熟悉,无法阅读 Couchdb 源代码并弄清楚发生了什么。为什么文档的摘要与其内容不匹配,或者被压缩了?
答案1
不确定您是否已经解决了这个问题,但我开始沿着同样的路径前进。查看了源代码后,似乎摘要计算发生在压缩之前,因此我认为压缩不会对摘要值产生影响。
我能够使用节点中的以下内容重现 CouchDB 为附件生成的 md5 摘要:
var crypto = require('crypto');
var attachmentData = "base64-encoded-data"
var buf = new Buffer(attachmentData, 'base64')
, md5 = crypto.createHash('md5').update(buf).digest('base64');
希望这可以为您或将来寻找详细信息的人提供帮助。
答案2
CouchDB 确实会在压缩可压缩文件后计算哈希值。
但是附件是使用 zlib 压缩的,我无法匹配它们所做的,所以唯一的解决方案似乎是在上传后获取它们的摘要并将其存储在某处。