0

I am running a Django app where I can upload files. Now I want to download the files using requests. I was trying to create a view where the file is downloaded, so I can then make a call with requests. But it doesn't quite work

My model: 

class FileCollection(models.Model):
    name = models.CharField(max_length=120, null=True, blank=True)
    store_file = models.FileField(storage=PrivateMediaStorage(), null=True, blank=True)
    creation_date = models.DateTimeField(null=True, blank=True)
My views



def fileview(request, *args, **kwargs):
    file = FileCollection.objects.first()
    file_path = file.store_file
    print(file_path)
    FilePointer = open(file_path, "r")
    response = HttpResponse(FilePointer, content_type='application/msexcel')
    response['Content-Disposition'] = 'attachment; filename=NameOfFile'

    return response


It tells me that TypeError: expected str, bytes or os.PathLike object, not FieldFile

If I pass in the url provided in the apiview/admin I get: FileNotFoundError: [Errno 2] No such file or directory

Also tried:

def fileview(request):
    path = FileCollection.objects.first()
    obj = path.store_file
    o = str(obj)
    file_path = os.path.join(settings.MEDIA_ROOT, o)
    print(file_path)
    if os.path.exists(file_path):
        with open(file_path, 'rb') as fh:
            response = HttpResponse(fh.read(),
                                    content_type="application/vnd.ms-excel")
            response[
                'Content-Disposition'] = 'inline; filename=' + os.path.basename(
                file_path)
            return response

but this gives me ValueError: The view file_storage_api.api.v1.views.fileview didn't return an HttpResponse object. It returned None instead.

Is that the right way to go?

I'm very grateful for help or hints. Thanks so much

Micromegas
  • 1,499
  • 2
  • 20
  • 49

1 Answers1

1
file_path = file.store_file

is not a file path but an instance of a FileField try using

file_path = file.store_file.name

and use the second snippet

EDIT: here is the code I use: l_targetFile is the path to the actual file

    l_prjPath = os.path.realpath(os.path.dirname(__file__)).replace(<adapt the path here>)
    l_userFileName= <file field>.name.replace('<upload to sub-dir>','')
    l_targetFile = l_prjPath + '/media/' + l_fileObj.file_obj.name
    #return the file
    response = FileResponse(open(l_targetFile, 'rb'),\
                            (l_responseDisposition == 'attachment'))        

    #process the filename as stored on the local machine in case of download
    try:
        #check if it will throw
        l_tmpUserName = l_userFileName.encode('ascii')

        #no error use the non-encoded filename
        l_fileExpr = 'filename="{0}"'.format(l_userFileName)
    except UnicodeEncodeError:
        # Handle a non-ASCII filename
        l_fileExpr = "filename*=utf-8''{}".format(quote(l_userFileName))

    response['Content-Disposition'] = '{0};{1};'.format(l_responseDisposition,l_fileExpr)
    if '.pdf' in l_userFileName:
        response['Content-Type'] = 'application/pdf'
    elif l_dataSource == CMSArchiveEntry.SOURCE_TAG:
        response['Content-Type'] = 'text/html; charset=utf-8'
    return response
tstoev
  • 1,415
  • 11
  • 12
  • thanks my friend! When I try this I still get ```File not found error``` even though the file is there. It is in an AWS bucket, but still django should find it right? – Micromegas Oct 23 '19 at 07:10
  • I managed by doing: ```file_path = file.store_file read_file = file_path.read()``` – Micromegas Oct 23 '19 at 07:23
  • the AWS should not change anything, but there is obviously some problem with configuration. .name should return a path that is relative to the media root. I will add the code I am using to render file responces below – tstoev Oct 23 '19 at 08:32