diff --git a/ietf/meeting/utils.py b/ietf/meeting/utils.py index 470795811..e3d8c830e 100644 --- a/ietf/meeting/utils.py +++ b/ietf/meeting/utils.py @@ -727,7 +727,7 @@ def save_session_minutes_revision(session, file, ext, request, encoding=None, ap def handle_upload_file(file, filename, meeting, subdir, request=None, encoding=None): """Accept an uploaded materials file - This function takes a file object, a filename and a meeting object and subdir as string. + This function takes a _binary mode_ file object, a filename and a meeting object and subdir as string. It saves the file to the appropriate directory, get_materials_path() + subdir. If the file is a zip file, it creates a new directory in 'slides', which is the basename of the zip file and unzips the file in the new directory. @@ -749,9 +749,18 @@ def handle_upload_file(file, filename, meeting, subdir, request=None, encoding=N pass # if the file is already gone, so be it with (path / filename).open('wb+') as destination: + # prep file for reading + if hasattr(file, "chunks"): + chunks = file.chunks() + else: + try: + file.seek(0) + except AttributeError: + pass + chunks = [file.read()] # pretend we have chunks + if filename.suffix in settings.MEETING_VALID_MIME_TYPE_EXTENSIONS['text/html']: - file.open() - text = file.read() + text = b"".join(chunks) if encoding: try: text = text.decode(encoding) @@ -778,11 +787,8 @@ def handle_upload_file(file, filename, meeting, subdir, request=None, encoding=N f"please check the resulting content. " )) else: - if hasattr(file, 'chunks'): - for chunk in file.chunks(): - destination.write(chunk) - else: - destination.write(file.read()) + for chunk in chunks: + destination.write(chunk) # unzip zipfile if is_zipfile: diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index c3494a13b..cf7c67ac4 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -33,6 +33,7 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import login_required from django.core.exceptions import ValidationError +from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import URLValidator from django.urls import reverse,reverse_lazy from django.db.models import F, Max, Q @@ -2795,6 +2796,17 @@ class UploadOrEnterAgendaForm(UploadAgendaForm): elif submission_method == "enter": require_field("content") + def get_file(self): + """Get content as a file-like object""" + if self.cleaned_data.get("submission_method") == "upload": + return self.cleaned_data["file"] + else: + return SimpleUploadedFile( + name="uploaded.md", + content=self.cleaned_data["content"].encode("utf-8"), + content_type="text/markdown;charset=utf-8", + ) + def upload_session_agenda(request, session_id, num): # num is redundant, but we're dragging it along an artifact of where we are in the current URL structure session = get_object_or_404(Session,pk=session_id) @@ -2815,21 +2827,8 @@ def upload_session_agenda(request, session_id, num): if request.method == 'POST': form = UploadOrEnterAgendaForm(show_apply_to_all_checkbox,request.POST,request.FILES) if form.is_valid(): - submission_method = form.cleaned_data['submission_method'] - if submission_method == "upload": - file = request.FILES['file'] - _, ext = os.path.splitext(file.name) - else: - if agenda_sp: - doc = agenda_sp.document - _, ext = os.path.splitext(doc.uploaded_filename) - else: - ext = ".md" - fd, name = tempfile.mkstemp(suffix=ext, text=True) - os.close(fd) - with open(name, "w") as file: - file.write(form.cleaned_data['content']) - file = open(name, "rb") + file = form.get_file() + _, ext = os.path.splitext(file.name) apply_to_all = session.type.slug == 'regular' if show_apply_to_all_checkbox: apply_to_all = form.cleaned_data['apply_to_all']