在django中下载csv文件

spy*_*der 7 django download

我正在尝试使用HttpResponse下载CSV文件,以确保浏览器将其视为附件.我按照此处提供的说明操作,但我的浏览器未提示"另存为"对话框.我无法弄清楚我的功能有什么问题.所有帮助表示赞赏.

  dev savefile(request):
        try:
            myfile = request.GET['filename']
            filepath = settings.MEDIA_ROOT + 'results/'
            destpath = os.path.join(filepath, myfile)
            response = HttpResponse(FileWrapper(file(destpath)), mimetype='text/csv' ) 
            response['Content-Disposition'] = 'attachment; filename="%s"' %(myfile)
            return response
        except Exception, err:
            errmsg = "%s"%(err)
            return HttpResponse(errmsg)

祝帕特节快乐!

Ofr*_*viv 9

如果文件是静态的(即不是专门为此请求生成的),则无论如何都不应该通过django提供它.您应该配置一些由Web服务器提供服务的路径(如/ static /),并保存所有django开销.

如果文件是动态的,有2个选项:

  1. 在内存中创建它并从django提供它.
  2. 在磁盘上创建它,并返回一个HttpResponseRedirect,以便您的Web服务器处理下载本身(如果文件非常大,您应该使用此选项).

至于动态提供它,我一直在使用以下代码(这是ExcelResponse的简化版本)

import StringIO
from django.db.models.query import ValuesQuerySet, QuerySet

class CSVResponse(HttpResponse):

  def __init__(self, data, output_name='data', headers=None, encoding='utf8'):

    # Make sure we've got the right type of data to work with
    valid_data = False
    if isinstance(data, ValuesQuerySet):
        data = list(data)
    elif isinstance(data, QuerySet):
        data = list(data.values())
    if hasattr(data, '__getitem__'):
        if isinstance(data[0], dict):
            if headers is None:
                headers = data[0].keys()
            data = [[row[col] for col in headers] for row in data]
            data.insert(0, headers)
        if hasattr(data[0], '__getitem__'):
            valid_data = True
    assert valid_data is True, "CSVResponse requires a sequence of sequences"

    output = StringIO.StringIO()
    for row in data:
        out_row = []
        for value in row:
            if not isinstance(value, basestring):
                value = unicode(value)
            value = value.encode(encoding)
            out_row.append(value.replace('"', '""'))
        output.write('"%s"\n' %
                     '","'.join(out_row))            
    mimetype = 'text/csv'
    file_ext = 'csv'
    output.seek(0)
    super(CSVResponse, self).__init__(content=output.getvalue(),
                                        mimetype=mimetype)
    self['Content-Disposition'] = 'attachment;filename="%s.%s"' % \
        (output_name.replace('"', '\"'), file_ext)
Run Code Online (Sandbox Code Playgroud)

要使用它,只需使用返回CSVResponse(...)传递列表列表,一个dicts列表(使用相同的键),一个QuerySet,一个ValuesQuerySet


Cer*_*rin 5

您是否尝试指定内容类型?例如

response['Content-Type'] = 'application/x-download';
Run Code Online (Sandbox Code Playgroud)

编辑:

注意,此代码成功触发了"另存为"对话框.注意我直接在mimetype参数中指定"application/x-download".您还可能需要重新检查代码,并确保文件路径正确,并且FileWrapper()没有做一些奇怪的事情.

def save_file(request):
    data = open(os.path.join(settings.PROJECT_PATH,'data/table.csv'),'r').read()
    resp = django.http.HttpResponse(data, mimetype='application/x-download')
    resp['Content-Disposition'] = 'attachment;filename=table.csv'
    return resp
Run Code Online (Sandbox Code Playgroud)


spy*_*der 3

感谢大家的建议。我选择了一些新技巧:)但是我想我已经在这里找到了问题的答案: 通过 AJAX 下载 CSV 我的“savefile”函数是通过 Ajax 请求调用的,而且 ajax 似乎有一个限制,其中“另存为对话框”无论 HTTP 标头是什么,都不会出现“。

我应该提到我使用 Ajax 来调用这个函数,但我从来没有想到这可能是一个问题。:) 谢谢 StackOverflow!