【发布时间】:2023-03-11 04:08:01
【问题描述】:
我有一个基于网络的自制文件系统,允许用户以 zip 格式下载文件;但是,我在生产系统上不存在的本地盒子上进行开发时发现了一个问题。
在 linux 中,这不是问题(本地开发盒是 windows 系统)。
我有以下代码
algo = CipherType('AES-256', 'CBC')
decrypt = DecryptCipher(algo, cur_share.key[:32], cur_share.key[-16:])
file = open(settings.STORAGE_ROOT + 'f_' + str(cur_file.id), 'rb')
temp_file = open(temp_file_path, 'wb+')
data = file.read(settings.READ_SIZE)
while data:
dec_data = decrypt.update(data)
temp_file.write(dec_data)
data = file.read(settings.READ_SIZE)
# Takes a dump right here!
# error in cipher operation (wrong final block length)
final_data = decrypt.finish()
temp_file.write(final_data)
file.close()
temp_file.close()
上面的代码打开一个文件,并(使用当前文件共享的密钥)解密文件并将其写入一个临时位置(稍后将被填充到一个 zip 文件中)。
我的问题在file = open(settings.STORAGE_ROOT + 'f_' + str(cur_file.id), 'rb') 行。如果我不指定'rb',Windows 会非常关心二进制文件,因此文件将不会在数据读取循环中结束;但是,由于某种原因,由于我也在写信给temp_file,它永远不会完全读取到文件的末尾...除非我在 b 'rb+' 之后添加一个 +强>。
如果我将代码更改为file = open(settings.STORAGE_ROOT + 'f_' + str(cur_file.id), 'rb+'),一切都按预期工作,并且代码成功地抓取了整个二进制文件并对其进行解密。如果我不添加加号,它会失败并且无法读取整个文件......
代码的另一部分(用于下载单个文件)读取(无论操作系统如何都可以完美运行):
algo = CipherType('AES-256', 'CBC')
decrypt = DecryptCipher(algo, cur_share.key[:32], cur_share.key[-16:])
file = open(settings.STORAGE_ROOT + 'f_' + str(cur_file.id), 'rb')
filename = smart_str(cur_file.name, errors='replace')
response = HttpResponse(mimetype='application/octet-stream')
response['Content-Disposition'] = 'attachment; filename="' + filename + '"'
data = file.read(settings.READ_SIZE)
while data:
dec_data = decrypt.update(data)
response.write(dec_data)
data = file.read(settings.READ_SIZE)
# no dumps to be taken when finishing up the decrypt process...
final_data = decrypt.finish()
temp_file.write(final_data)
file.close()
temp_file.close()
澄清
密码错误可能是因为未完整读取文件。例如,我有一个 500MB 的文件,每次读取 64*1024 个字节。我一直读到我没有收到更多字节,当我没有在 Windows 中指定 b 时,它会循环两次并返回一些糟糕的数据(因为 python 认为它正在与字符串文件而不是二进制文件交互)。
当我指定 b 时,需要 10-15 秒才能完全读取文件,但它会成功完成,并且代码正常完成。
当我从源文件读入时同时写入另一个文件时(如第一个示例所示),如果我没有指定 rb+,它会显示与甚至没有指定 b 相同的行为,即在关闭句柄并继续之前,它只从文件中读取几个片段,我最终得到一个不完整的文件并且解密失败。
【问题讨论】:
-
“在这里转储”、“不会读到结束”等是什么意思?究竟会发生什么?
-
@abarnert 澄清添加。 - 需要注意的是,我知道添加
+似乎可以解决这个问题,但我想知道它为什么会在 Windows 上运行以及打开文件句柄时发生了什么。这方面的python文档很薄弱。 -
在另一段代码中没有
decrypt = DecryptCipher(algo, cur_share.key[:32], cur_share.key[-16:]),所以它还在使用第一段的decrypt吗? -
@mart 它正在创建另一个解密对象,但这对于手头的问题并不重要。密码问题是python没有正确读取文件内容的结果,除非我指定模式
'rb+',其中'rb'就足够了...... -
@MikeMcMahon:我对你的澄清感到困惑。你说没有
b它循环循环两次,然后你说使用b而不是+它与没有b做同样的事情,然后你说它读取了几个片段然后关闭手柄。这是矛盾的。两者都没有任何意义。r和rb之间的唯一区别是r将转换行尾(因此每对匹配 0D 0A 的字节将被单个字节 0A 替换)。
标签: python python-2.7 file-io