diff --git a/hypha/apply/funds/views/__init__.py b/hypha/apply/funds/views/__init__.py
index 16b86225cf..ac80b7bdbe 100644
--- a/hypha/apply/funds/views/__init__.py
+++ b/hypha/apply/funds/views/__init__.py
@@ -1,5 +1,6 @@
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import UserPassesTestMixin
+from django.http import Http404
from django.shortcuts import get_object_or_404, render
from django.utils.decorators import method_decorator
from django_filters.views import FilterView
@@ -56,6 +57,13 @@ def get_media(self, *args, **kwargs):
path_to_file = generate_private_file_path(
self.submission.pk, field_id, file_name
)
+ try:
+ if not self.storage.exists(path_to_file):
+ raise Http404
+ except Http404:
+ raise
+ except Exception as e:
+ raise Http404 from e
return self.storage.open(path_to_file)
def test_func(self):
diff --git a/hypha/apply/funds/views/submission_edit.py b/hypha/apply/funds/views/submission_edit.py
index 241b40c18e..e7a6a45485 100644
--- a/hypha/apply/funds/views/submission_edit.py
+++ b/hypha/apply/funds/views/submission_edit.py
@@ -248,13 +248,23 @@ def get_form_kwargs(self):
def get_placeholder_file(self, initial_file):
if not isinstance(initial_file, list):
return PlaceholderUploadedFile(
- initial_file.filename, size=initial_file.size, file_id=initial_file.name
+ initial_file.filename,
+ size=self._safe_file_size(initial_file),
+ file_id=initial_file.name,
)
return [
- PlaceholderUploadedFile(f.filename, size=f.size, file_id=f.name)
+ PlaceholderUploadedFile(
+ f.filename, size=self._safe_file_size(f), file_id=f.name
+ )
for f in initial_file
]
+ def _safe_file_size(self, stream_file):
+ try:
+ return stream_file.storage.size(stream_file.name)
+ except Exception:
+ return 0
+
def save_draft_and_refresh_page(self, form) -> HttpResponseRedirect:
self.object.create_revision(draft=True, by=self.request.user)
form.delete_temporary_files()
diff --git a/hypha/apply/stream_forms/files.py b/hypha/apply/stream_forms/files.py
index b68bd65a89..7214866252 100644
--- a/hypha/apply/stream_forms/files.py
+++ b/hypha/apply/stream_forms/files.py
@@ -82,15 +82,27 @@ def size(self):
return self.file.size
return self.storage.size(self.name)
+ def _check_exists(self):
+ """Fetch modification time once; caches both existence and the date."""
+ if not hasattr(self, "_exists_cache"):
+ try:
+ self._modification_time_cache = self.storage.get_modified_time(
+ self.name
+ ).date()
+ self._exists_cache = True
+ except Exception:
+ self._modification_time_cache = "–"
+ self._exists_cache = False
+
@property
- def modification_time(self):
- # Wrap in a try for local developments where files might not always exist.
- try:
- modified_time = self.storage.get_modified_time(self.name).date()
- except FileNotFoundError:
- modified_time = "–"
+ def exists(self):
+ self._check_exists()
+ return self._exists_cache
- return modified_time
+ @property
+ def modification_time(self):
+ self._check_exists()
+ return self._modification_time_cache
def serialize(self):
return {
diff --git a/hypha/apply/stream_forms/templates/stream_forms/includes/file_field.html b/hypha/apply/stream_forms/templates/stream_forms/includes/file_field.html
index d53fdc6dad..e8c0b271f4 100644
--- a/hypha/apply/stream_forms/templates/stream_forms/includes/file_field.html
+++ b/hypha/apply/stream_forms/templates/stream_forms/includes/file_field.html
@@ -1,21 +1,39 @@
{% load i18n heroicons apply_tags %}
-
-
- {% heroicon_mini "document-text" class="inline align-text-bottom" aria_hidden=true %}
- {{ file.filename|truncatechars_middle:45 }}
-
- {% trans "uploaded" %}
- •
-