Search code examples
pythondjangodjango-rest-frameworkhttpresponsecontent-disposition

How can I download a temporary file in Django?


I'm learning how to serve temporary files in Django, and even after reading the docs I'm having some trouble finishing it all up. These files are dynamically generated temporarily from user input.

def get_queryset(self):
    gcode = "/home/bradman/Documents/Programming/DjangoWebProjects/3dprinceprod/fullprince/media/uploads/tmp/skull.gcode"
    test_file = open(gcode, 'r')

    response = HttpResponse(test_file, content_type='text/plain')
    response['Content-Disposition'] = "attachment; filename=%s.gcode" % title
    print (response)
    return response

The code above should place my temporary-gcode file from my server into an HttpResponse object, and the return function should download the file. It even slows down like its downloading, but there is no file once it's finished.

This question provided most of the useful info and this one was helpful as well, but I can't get it working and don't know how else to test it. I'm not sure if moving to apache or something is appropriate since I have user permission issues and these files are immediately deleted after downloaded. I've checked that "gcode" is the directory url, and gcode content_type should be text/plain. So basically, how can I make my response actually download?

Edit1

Here is the full code, not just the problematic section.

class SubFileViewSet(viewsets.ModelViewSet):
    queryset = subfiles.objects.all()
    serializer_class = SubFilesSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                          IsOwnerOrReadOnly,)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

    def get_queryset(self):
        req = self.request
        make = req.query_params.get('make')
        model = req.query_params.get('model')
        plastic = req.query_params.get('plastic')
        quality = req.query_params.get('qual')
        filenum = req.query_params.get('fileid')
        hotend = req.query_params.get('hotendtemp')
        bed = req.query_params.get('bedtemp')


        if make and model and plastic and quality and filenum:            

            filepath = subfiles.objects.values('STL', 'FileTitle').get(fileid = filenum)

            path = filepath['STL']
            title =  filepath['FileTitle']    

            gcode = TheMagic(
                make=make, 
                model=model, 
                plastic=plastic, 
                qual=quality, 
                path=path, 
                title=title, 
                hotendtemp=hotend,
                bedtemp=bed)

            test_file = open(gcode, 'r')
            response = HttpResponse(test_file, content_type='text/plain')
            response['Content-Disposition'] = "attachment; filename=%s.gcode" % title
            print (response.content)
            return response

        else:
            print ('normal or non complete download')
            return self.queryset

I'm using Django Rest Framework and trying to create a dynamic response from my API get request to react to parameters given in the URL. So I send a get request passing variables as parameters, it creates a file based on those variables, and lastly sends back the created file. All of this already works except the actual file download at the end. The get request returns an HTTP 500 error.


Solution

  • For test, you can create view like that:

    def download_file(request):
        gcode = "/home/bradman/Documents/Programming/DjangoWebProjects/3dprinceprod/fullprince/media/uploads/tmp/skull.gcode"
        resp = HttpResponse('')
    
        with  open(gcode, 'r') as tmp:
            filename = tmp.name.split('/')[-1]
            resp = HttpResponse(tmp, content_type='application/text;charset=UTF-8')
            resp['Content-Disposition'] = "attachment; filename=%s" % filename
    
        return resp
    

    If you test in shell (django):

    print(response.content)
    

    At end of your code to ensure that your file has been read.