【问题标题】:How can I display a TemporaryUploadedFile from Django in HTML as an image?如何在 HTML 中将来自 Django 的 TemporaryUploadedFile 显示为图像?
【发布时间】:2018-03-12 11:07:45
【问题描述】:

在 Django 中,我编写了一个表单,您可以在其中上传一张图片。上传图片后,图片被传递给另一个类型为 TemporaryUploadedFile 的方法,在执行该方法后,它会被传递给 HTML 页面。

我想做的是将 TemporaryUploadedFile 显示为 HTML 中的图像。对我来说这听起来很简单,但我无法在 StackOverflow 或 Google 上找到问题的答案:如何在 HTML 中显示 TemporaryUploadedFile 而无需先保存,因此是我的问题。

感谢所有帮助。


编辑 1:

在调试时提供有关代码和变量的更多信息。

input_image = next(iter(request.FILES.values()))
output_b64 = (input_image.content_type, str(base64.b64encode(input_image.read()), 'utf8'))

【问题讨论】:

  • 嗯,这很奇怪。图像的大小约为 4 MB,但编码的字符串只有几个字节。我猜input_image.read() 没有读取整个文件,因为它大于 2.5 MB 并且 Django 正在将此文件分成块。你能用一个几百千字节的小图像试试这个,然后告诉我这是否有效。如果这是问题,我可能需要添加另一个答案。
  • 我调整了图像的大小,现在它的大小是 116KB。我还尝试了一些来自谷歌的图片。只是为了检查我使用的图像集没有以任何方式损坏。很遗憾,但它没有成功,图像仍然没有显示。我想知道原因可能是什么。
  • 嗨,我刚刚使用 Django 2.0、Python 3.6 进行了测试,对我来说一切正常,无论是大小图像,都一样。我不知道为什么它不适合你。但我希望你能弄清楚。一切顺利。
  • 感谢您的帮助。我将尝试修复它,至少我现在知道它应该可以工作,因此问题可能出在我的应用程序的其他地方,当我修复它时,我将解决方案发布在这里。

标签: html django python-3.x


【解决方案1】:

好吧,您可以将图像编码为base64,并使用数据url作为src的值。

base64 数据 url 如下所示:

<img src="data:image/png;base64,SGLAFdsfsafsf098sflf">
               \_______/        \__________________/
                   |                     |
                File type        base64 encoded data

阅读Mozilla docs 了解有关数据网址的更多信息。

以下是一些相关代码:

import base64

def my_view(request):
    # assuming `image` is a <TemporaryUploadedFile object>

    image_b64 = base64.b64encode(image.read())
    # For Python 3, see UPDATE below
    image_type = image.content_type # png or jpeg or something else
    return render('template', {'image_b64': image_b64, 'image_type': image_type})

然后在你的模板中:

<img src="data:{{ image_type }};base64,{{ image_b64 }}">

更新:

在 Python 3 中,base64 编码的对象是类似字节的对象,因此需要多一步才能在模板中正确显示图像。您必须将其从字节转换为字符串。示例:

image_b64 = str(image_b64, 'utf8')

【讨论】:

  • 我尝试了您的解决方案,但遇到了一个问题,即在生成图像 src 时,它在 HTML 中看起来像这样:&lt;img src="data:image/png;base64,b'puGSpAAAAABJRU5ErkJggg=='"&gt;。与您的相比,src 中的字符串看起来很奇怪,不仅因为它有一个“b”,其中有两个撇号表示它是一个字节字符串,还因为末尾有两个等号。你能帮我弄清楚我在这里做错了什么吗?
  • @user3473161 哦,是的。您必须使用 Python 3。base64 编码的对象在 Python 3 中是类似字节的对象,而在 Python 2 中是类似 str 的对象。这就是为什么开头有 b 的原因。我会尽快用解决方案更新我的答案。
  • 我很期待:p。是的,目前我使用的是 64 位版本的 Python 3.6.3。
  • 我希望我没有给你太多麻烦,但我无法解决它。为了提供更多关于出了什么问题的信息,我在我的问题中放入了一小段代码以及来自调试器的信息。
  • Python 3 的更新解决方案对我来说效果很好。谢谢!
【解决方案2】:

我要感谢 xyres 将我推向正确的方向。如您所见,我在下面的代码中使用了他的部分解决方案:

# As input I take one image from the form.
temp_uploaded_file = next(iter(request.FILES.values()))

# The TemporaryUploadedFile is converted to a Pillow Image
input_image = pil_image.open(temp_uploaded_file)

# The input image does not have a name so I set it afterwards. (This step, of course, is not mandatory)
input_image.filename = temp_uploaded_file.name

# The image is saved to an InMemoryFile
output = BytesIO()
input_image.save(output, format=img.format)

# Then the InMemoryFile is encoded
img_data = str(base64.b64encode(output.getvalue()), 'utf8')
output_b64 = ('image/' + img.format, img_data)

# Pass it to the template
return render(request, 'visualsearch/similarity_output.html', {
    "output_image": output_b64
})

在模板中:

<img id="output_image" src="data:{{ image.0 }};base64,{{ image.1 }}">

当前的解决方案有效,但我认为它并不完美,因为我希望它可以用更少的代码更快地完成,所以如果您知道如何更好地完成此操作,欢迎在此处发布您的答案。

【讨论】:

    猜你喜欢
    • 2015-12-04
    • 2016-08-28
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 2015-04-15
    • 1970-01-01
    • 2013-04-24
    相关资源
    最近更新 更多