Search code examples
djangoamazon-s3django-storage

Django download S3 file and include in zip


I've this piece of code to add files to a zip in Django. Works fine when media is local but when using an s3 bucket I get the following error:

FileNotFoundError at /en/admin/certification/application/

[Errno 2] No such file or directory: 'https://bucket-name.s3.amazonaws.com/media/application_files/name_of_the_pdf.pdf'

Here's the code:

    filename = settings.MEDIA_ROOT  + q.user.username + '-' + q.certification.standard.name + '-' + q.certification.name
    zf = zipfile.ZipFile(byte, "w")
    zipped_files = []
    zip_filename = filename + '.zip'
    csv_filename = filename + '.csv'
    with open(csv_filename, 'w') as csvfile:
        filewriter = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
        for answer in q.answer_set.all():
            if answer.question.question_type in ['file', 'files']: 
                if answer.f :
                    if 'RDS_HOSTNAME' in os.environ: 
                        res = answer.f.url
                    else: res = settings.BASE_DIR + answer.f.url
                    zf.write(res)
            elif answer.question.question_type == 'text' : res = answer.text
            else : res = answer.checkbox.name

            filewriter.writerow([answer.question.question, res])
    zf.write(csv_filename)
    zf.close()

    resp = HttpResponse(
        byte.getvalue(), content_type="application/x-zip-compressed")
    resp['Content-Disposition'] = 'attachment; filename=%s' % zip_filename

And the traceback:

Traceback:

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/contrib/admin/options.py" in wrapper
  604.                 return self.admin_site.admin_view(view)(*args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapped_view
  142.                     response = view_func(request, *args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  44.         response = view_func(request, *args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/contrib/admin/sites.py" in inner
  223.             return view(request, *args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapped_view
  142.                     response = view_func(request, *args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/contrib/admin/options.py" in changelist_view
  1701.                 response = self.response_action(request, queryset=cl.get_queryset(request))

File "/opt/python/run/venv/local/lib/python3.6/site-packages/django/contrib/admin/options.py" in response_action
  1400.             response = func(self, request, queryset)

File "/opt/python/current/app/certification/admin_actions.py" in download_application
  31.                         zf.write(res)

File "/usr/lib64/python3.6/zipfile.py" in write
  1617.         zinfo = ZipInfo.from_file(filename, arcname)

File "/usr/lib64/python3.6/zipfile.py" in from_file
  507.         st = os.stat(filename)

Exception Type: FileNotFoundError at /en/admin/certification/application/
Exception Value: [Errno 2] No such file or directory: 'https://bucket-name.s3.amazonaws.com/media/application_files/name_of_the_pdf.pdf'

I have changed the bucket and file names to examples.

What have I got wrong?


Solution

  • This is how I resolved it:

                        if answer.f :
                            if 'RDS_HOSTNAME' in os.environ: 
                                res = answer.f.url
                                response = requests.get(answer.f.url)
                                zf.writestr(answer.f.url, response.content)
                            else: 
                                res = settings.BASE_DIR + answer.f.url
                                zf.write(res)