I am trying to download a CSV file using HttpResponse to make sure that the browser treats it as an attachment. I follow the instructions provided here but my browser does not prompt a "Save As" dialog. I cannot figure out what is wrong with my function. All help is appreciated.
  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)
Happy Pat's day!
Did you try specifying the content-type? e.g.
response['Content-Type'] = 'application/x-download';
Edit:
Note, this code successfully triggers a "Save As" dialog for me. Note I specify "application/x-download" directly in the mimetype argument. You also might want to recheck your code, and ensure your file path is correct, and that FileWrapper() isn't doing something weird.
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
                        If the file is static (i.e not generated specifically for this request) you shouldn't be serving it through django anyway. You should configure some path (like /static/) to be served by your webserver, and save all the django overhead.
If the file is dynamic, there are 2 options:
As for serving it dynamically, I've been using the following code (which is a simplified version of 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)
To use it, just use return CSVResponse(...) passing in a list of lists, a list of dicts (with same keys), a QuerySet, a ValuesQuerySet
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With