使用Python 3.x将文件写入磁盘

3
使用BottlePy,我使用以下代码上传文件并将其写入磁盘:
upload = request.files.get('upload')
raw = upload.file.read()
filename = upload.filename
with open(filename, 'w') as f:
    f.write(raw)
return "You uploaded %s (%d bytes)." % (filename, len(raw))

它每次都返回正确的字节数。

上传对于像.txt, .php, .css这样的文件正常工作...

但是对于其他文件,如.jpg, .png, .pdf, .xls等,则会导致文件损坏。

我尝试更改open()函数。

with open(filename, 'wb') as f:

它返回以下错误:
TypeError('必须是字节或缓冲区,而不是字符串',)
我猜这与二进制文件有关?
是否需要安装Python的附加组件才能上传任何文件类型?
更新
只是为了确保,如@thkang所指出的那样,我尝试使用bottlepy的dev版本和内置方法.save()编写此代码。
upload = request.files.get('upload')
upload.save(upload.filename)

它返回完全相同的异常错误。

TypeError('must be bytes or buffer, not str',)

更新2
以下是最终代码,它“有效”(不会弹出错误TypeError('must be bytes or buffer, not str',)):
upload = request.files.get('upload')
raw = upload.file.read().encode()
filename = upload.filename
with open(filename, 'wb') as f:
    f.write(raw)

很遗憾,结果是一样的:每个.txt文件都能正常工作,但其他文件如.jpg.pdf等都损坏了。
我还注意到这些文件(损坏的文件)比原始文件(上传前)要大。
这个二进制问题必须是Python 3x的问题。
注意:
  • 我使用Python 3.1.3
  • 我使用BottlePy 0.11.6 (bottle.py原始文件,没有进行2to3或其他任何处理)

文件对象上不是有.save()方法吗? - thkang
是的,它在开发文档中,我尝试了但出现了错误AttributeError('save',)(我的版本是0.11.6)。 - Koffee
2个回答

3

试试这个:

upload = request.files.get('upload')

with open(upload.file, "rb") as f1:
    raw = f1.read()
    filename = upload.filename
    with open(filename, 'wb') as f:
        f.write(raw)

    return "You uploaded %s (%d bytes)." % (filename, len(raw))

更新

尝试使用value

# Get a cgi.FieldStorage object
upload = request.files.get('upload')

# Get the data
raw = upload.value;

# Write to file
filename = upload.filename
with open(filename, 'wb') as f:
    f.write(raw)

return "You uploaded %s (%d bytes)." % (filename, len(raw))

更新2

请参考此帖子,它似乎与您尝试的内容相同...

# Test if the file was uploaded
if fileitem.filename:

   # strip leading path from file name to avoid directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   open('files/' + fn, 'wb').write(fileitem.file.read())
   message = 'The file "' + fn + '" was uploaded successfully'

else:
   message = 'No file was uploaded'

我尝试了,第一行open()返回一个错误TypeError("invalid file: <_io.TextIOWrapper name=6 encoding='utf-8'>",)(对于任何类型的文件都会发送此错误)。 - Koffee
@Koffee 请分享您对 request 的声明。 - ATOzTOA
我尝试了所有的方法,但一直收到相同的错误 TypeError('must be bytes or buffer, not str',)。我使用了encode()函数来将字符串转换为字节,但结果仍然相同。我强烈怀疑是 Python 3x 和字节之间存在问题(请参见更新)。 - Koffee
1
我刚刚尝试了您在更新2中提供的链接中的完整代码,它也返回错误TypeError('must be bytes or buffer, not str',) - Koffee

2
在Python 3x中,所有字符串现在都是Unicode编码的,因此您需要转换此文件上传代码中使用的read()函数。 read()函数也返回Unicode字符串,您可以通过encode()函数将其转换为正确的字节。
使用我第一个问题中包含的代码,并替换该行:
raw = upload.file.read()

使用

raw = upload.file.read().encode('ISO-8859-1')

就这些啦;)

更多阅读:http://python3porting.com/problems.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接