【问题标题】:Trouble creating HttpResponse for xml download, Django为 xml 下载创建 HttpResponse 时出现问题,Django
【发布时间】:2015-07-06 07:45:10
【问题描述】:

我正在尝试让用户下载我生成的 xml 文件。

这是我的代码:

tree.write('output.xml', encoding="utf-16")
# Pathout is the path to the output.xml
xmlFile = open(pathout, 'r')
myfile = FileWrapper(xmlFile.read())
response = HttpResponse(myfile, content_type='application/xml')
response['Content-Disposition'] = 'attachment; filename='+filename
return response

当我尝试创建我的回复时,我得到了这个异常:

'\\'str\\' object has no attribute \\'read\\''

无法弄清楚我做错了什么。有什么想法吗?

编辑: 当我使用此代码时,我没有收到任何错误,但下载的文件是空的

tree.write('output.xml', encoding="utf-16")
xmlFile = open(pathout, 'r')
myfile = FileWrapper(xmlFile)

response = HttpResponse(myfile, content_type='application/xml')
response['Content-Disposition'] = 'attachment; filename='+filename
return response

【问题讨论】:

  • 我在想,你真的要存储文件吗?你也可以使用 Django 模板来渲染它。
  • @Wtower 好问题但错误的解决方案 - 您不需要模板来呈现 xml,只需将其(以字符串形式)传递给 HttpResponse 对象。
  • 用户必须能够存储文件,只要它可以工作,我就不需要将它存储在服务器上:) @Wtower
  • @brunodesthuilliers 你是什么意思错误的解决方案?我发表了评论而不是答案,您的评论似乎没有回答。在Django中你无论如何都不必使用模板,这并不意味着它是实用的。
  • @Wtower 我的意思是,当您可以将 XML 直接传递给 HttpResponse 对象时,使用 Django 模板来呈现已经格式良好的 XML 是没有用的。

标签: python django download attachment


【解决方案1】:

您正在调用 xmlFile.read() - 它会产生一个字符串 - 并将结果传递给 FileWrapper() ,它需要一个可读的类似文件的对象。您应该将xmlFile 传递给FileWrapper,或者根本不使用FileWrapper 并将xmlFile.read() 的结果作为HttpResponse 正文传递。

请注意,如果您正在动态创建 xml(根据您的 sn-p 的第一行似乎是这种情况),将其写入磁盘仅在几行后将其读回既浪费时间又浪费资源和竞争条件的潜在原因。你可能想看看https://docs.python.org/2/library/xml.etree.elementtree.html#xml.etree.ElementTree.tostring

【讨论】:

  • 执行此操作时没有错误,我可以下载文件。问题是它现在完全是空的。
  • elementtree tostring 为我解决了问题 :) 谢谢
【解决方案2】:

您正在读取文件并将结果字符串传递给 FileWrapper,而不是传递实际的文件对象。

myfile = FileWrapper(xmlFile)

【讨论】:

  • 这里和上面一样,没有错误但是文件是空的
【解决方案3】:

或者从其他答案中,我建议通过使用 Django 模板系统来完全解决这个问题:

from django.http import HttpResponse
from django.template import Context, loader

def my_view(request):
    # View code here...
    t = loader.get_template('myapp/myfile.xml')
    c = Context({'foo': 'bar'})
    response = HttpResponse(t.render(c), content_type="application/xml")
    response['Content-Disposition'] = 'attachment; filename=...'
    return response

以这种方式创建一个myfile.xml 模板,该模板用于呈现正确的 xml 响应,而无需处理将任何文件写入文件系统。考虑到 确实没有其他需要创建 xml 并将其永久存储,这更加简洁和快速。

【讨论】:

  • 我通过使用myfile = ElementTree.tostring() command 设法做到了这一点。并且不必以这种方式在本地创建文件。
  • 太好了,我很高兴!我也只是想分享一下我的方式。
  • @Wtower:因为用户已经在使用ElementTree 创建 XML,重写他的代码以使用模板系统将是浪费时间。另外ElementTree 确保您将获得格式良好的 XML,而模板并非如此。
  • 我还没有让 OP 作者或任何人替换他的代码。我只是添加了另一种方法和观点。事情可能以多种方式发生,任何一种方式都有利有弊。
猜你喜欢
  • 2011-10-03
  • 1970-01-01
  • 2013-12-01
  • 1970-01-01
  • 2015-09-14
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多