Serving Excel(xlsx) file to the user for download in Django(Python)

Srht picture Srht · Nov 21, 2014 · Viewed 15.1k times · Source

I'm trying create and serve excel files using Django. I have a jar file which gets parameters and produces an excel file according to parameters and it works with no problem. But when i'm trying to get the produced file and serve it to the user for download the file comes out broken. It has 0kb size. This is the code piece I'm using for excel generation and serving.

def generateExcel(request,id):
    if os.path.exists('./%s_Report.xlsx' % id):
        excel = open("%s_Report.xlsx" % id, "r")
        output = StringIO.StringIO(excel.read())
        out_content = output.getvalue()
        output.close()
        response = HttpResponse(out_content,content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
        response['Content-Disposition'] = 'attachment; filename=%s_Report.xlsx' % id
        return response
    else:
        args = ['ServerExcel.jar', id]
        result = jarWrapper(*args) # this creates the excel file with no problem
        if result:
            excel = open("%s_Report.xlsx" % id, "r")
            output = StringIO.StringIO(excel.read())
            out_content = output.getvalue()
            output.close()
            response = HttpResponse(out_content,content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
            response['Content-Disposition'] = 'attachment; filename=%s_Report.xlsx' % id
            return response
        else:
            return HttpResponse(json.dumps({"no":"excel","no one": "cries"}))

I have searched for possible solutions and tried to use File Wrapper also but the result did not changed. I assume i have problem with reading the xlsx file into StringIO object. But dont have any idea about how to fix it

Answer

bruno desthuilliers picture bruno desthuilliers · Nov 21, 2014

Why on earth are you passing your file's content to a StringIO just to assign StringIO.get_value() to a local variable ? What's wrong with assigning file.read() to your variable directly ?

def generateExcel(request,id):
    path = './%s_Report.xlsx' % id # this should live elsewhere, definitely
    if os.path.exists(path):
        with open(path, "r") as excel:
            data = excel.read()

        response = HttpResponse(data,content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
        response['Content-Disposition'] = 'attachment; filename=%s_Report.xlsx' % id
        return response
    else:
        # quite some duplication to fix down there

Now you may want to check weither you actually had any content in your file - the fact that the file exists doesn't mean it has anything in it. Remember that you're in a concurrent context, you can have one thread or process trying to read the file while another (=>another request) is trying to write it.