文件流-ValueError:嵌入的空字节

时间:2019-09-15 01:52:52

标签: python python-3.x

我正在尝试通过HTTP请求下载.png图片,然后通过HTTP将其上传到其他位置。我的目标是避免将文件保存在磁盘上,以便在内存中对其进行处理。

我有以下代码:

  1. 下载文件并将其转换为字节数组:
resp = requests.get(
    'http://www.personal.psu.edu/crd5112/photos/PNG%20Example.png',
    stream=True)

img = BytesIO(resp.content)
  1. 将文件上传到远程HTTP存储库
data=open(img.getvalue()).read()

r = requests.post(url=url, data=data, headers=headers, auth=HTTPBasicAuth('user', 'user'))

读取字节数组时,我收到ValueError异常“嵌入的空字节”。

如果我将文件保存到磁盘上并按以下方式加载,则没有错误:

with open('file.png', 'wb') as pic:
  pic.write(img.getvalue())

关于如何在不将文件保存到磁盘的情况下实现它的任何建议?

3 个答案:

答案 0 :(得分:2)

是的,您可以执行此操作而无需保存到磁盘。在此之前,错误发生在行中

data=open(img.getvalue()).read()

由于使用不同编码的内置字符串操作不好,因此发生了此错误。 使用pillow库插入图像已实现的情况

from io import BytesIO
from PIL import Image    
img = BytesIO(resp.content)
-#data=open(img).read()
+data = Image.open(img)

这将为您提供以下对象类型

<class 'PIL.PngImagePlugin.PngImageFile'>

您可以将此数据变量用作上传请求中的数据

答案 1 :(得分:1)

@AmilaMGunawardana感谢您的指导。

我只需要将图像保存到单独的字节流中即可正确上传:

img = BytesIO(resp.content)

data = Image.open(img, 'r')

buf = BytesIO()

data.save(buf, 'PNG')

r = requests.post(url=url, data=buf.getvalue(), headers=headers, auth=HTTPBasicAuth('user', 'user'))

答案 2 :(得分:0)

我相信嵌入的空字节错误是由支持在您的代码中执行的任何操作的库的文件名输入要求引起的。通过使用 BytesIO 对象,这将自己呈现给该库,“就好像”它被包装在一个文件中一样。

这是我在尝试使用 tar 文件解决相同问题时使用的示例代码。此代码应该能够满足其他各种库的大多数文件输入要求。

我在这里找到的关键是使用 BytesIO 周围的 remote_file.content 对象作为文件对象传递到 tarfile.open。我尝试的其他技术不起作用。

from io import BytesIO
import requests
import tarfile

remote_file=requests.get ('https://download.site.com/files/file.tar.gz')

#Extract tarball contents to memory
tar=tarfile.open(fileobj=BytesIO(remote_file.content))
#Optionally print all folders / files within the tarball
print(tar.getnames())
tar.extractall('/home/users/Documents/target_directory/')

这消除了我在使用其他方法时遇到的 ValueError: embedded null byteexpected str, bytes or os.PathLike object, not _io.BytesIO 错误。