Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix batch downloading #1193

Merged
merged 1 commit into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions rodan-main/code/rodan/jobs/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import sys
import tempfile
import zipfile
import io, base64
import six

from celery import task, registry
from celery import Task
Expand All @@ -17,7 +19,6 @@
from django.db.models import Q, Case, Value, When, BooleanField
import PIL
from pybagit.bagit import BagIt
import six

import rodan # noqa
from rodan.models import (
Expand All @@ -43,7 +44,8 @@
from templated_mail.mail import BaseEmailMessage

# from rodan.celery import app

from celery.utils.log import get_task_logger
logger = get_task_logger(__name__)

class create_resource(Task):
name = "rodan.core.create_resource"
Expand Down Expand Up @@ -946,26 +948,29 @@ def send_templated_email(to, email_template, context):
@task(name="rodan.core.create_archive")
def create_archive(resource_uuids):
"""
Creates a zip archive of resosurces in memory for a user to download
Creates a zip archive of resources in memory for a user to download
"""
condition = Q()
for uuid in resource_uuids:
condition |= Q(uuid=uuid)
resources = Resource.objects.filter(Q(resource_file__isnull=False) & condition)
logger.info('Number of resources to archive: %d', resources.count())

# Don't return an empty zip file
if resources.count() == 0:
return None
temporary_storage = six.StringIO()
with zipfile.ZipFile(temporary_storage, "a", zipfile.ZIP_DEFLATED) as archive:

temporary_storage = io.BytesIO()
with zipfile.ZipFile(temporary_storage, "w", zipfile.ZIP_DEFLATED) as archive:
for resource in resources:
if not resource.resource_file:
print("{} has no file!".format(resource.name))
logger.warning("{} has no file!".format(resource.name))
continue

# determine a path that doesn't conflict
# Determine a path that doesn't conflict
filepath = resource.name + "." + resource.resource_type.extension
if filepath in archive.namelist():
for i in six.moves.range(1, sys.maxint):
for i in range(1, sys.maxsize):
filepath = resource.name + " ({}).".format(i) + resource.resource_type.extension
if filepath not in archive.namelist():
break
Expand All @@ -976,7 +981,7 @@ def create_archive(resource_uuids):
)

temporary_storage.seek(0)
return temporary_storage
return base64.b64encode(temporary_storage.getvalue()).decode('utf-8')


class test_work(Task):
Expand Down
10 changes: 7 additions & 3 deletions rodan-main/code/rodan/views/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import re
# import urlparse
import six.moves.urllib.parse
import base64, io

from celery import registry
from django.conf import settings
Expand Down Expand Up @@ -408,11 +409,14 @@ def get(self, request, format=None):

archive = registry.tasks['rodan.core.create_archive'] \
.si(resource_uuids).apply_async(queue="celery")
storage = archive.get()
if storage is None:
encoded_archive = archive.get()

if encoded_archive is None:
raise ValidationError({'resource_uuid': ["The specified resources must exist."]})

binary_data = base64.b64decode(encoded_archive)
response = FileResponse(
storage,
io.BytesIO(binary_data),
content_type="application/zip"
)
response['Content-Disposition'] = "attachment; filename=Archive.zip"
Expand Down
Loading