Fix a bug with deduplicated file download

This commit is contained in:
2026-01-14 11:36:09 +01:00
parent 8d899e4d9f
commit a254786ddc

View File

@@ -85,39 +85,42 @@ class DownloadFile(View):
# Find all models inheriting from PublishableFile # Find all models inheriting from PublishableFile
for model in apps.get_models(): for model in apps.get_models():
if issubclass(model, PrivateDocument) and not model._meta.abstract: if issubclass(model, PrivateDocument) and not model._meta.abstract:
try: # Due to deduplication, multiple documents may have
doc = model.objects.get(file__endswith=filename) # the same file name; if any is private, use a failsafe
if doc.private and not request.user.is_staff: # approach enforce access control
break docs = model.objects.filter(file__endswith=filename)
if not docs.exists():
file = doc.file
if not os.path.exists(file.path):
break
# in Nginx config, we need to map /private/ to
# the actual media files location with internal directive
# eg:
# location /private {
# internal;
# alias /path/to/media;
# }
if getattr(settings, "USE_X_ACCEL_REDIRECT", False):
response = HttpResponse()
response["Content-Type"] = ""
response["X-Accel-Redirect"] = f"/private/{file.name}"
else:
response = FileResponse(
open(file.path, "rb"), as_attachment=True
)
response["Content-Disposition"] = (
'{}; filename="{}"'.format(
disposition,
smart_str(os.path.basename(file.path))
)
)
return response
except model.DoesNotExist:
continue continue
if (
any(doc.private for doc in docs)
and not request.user.is_staff
):
break
file = docs.first().file
if not os.path.exists(file.path):
break
# in Nginx config, we need to map /private/ to
# the actual media files location with internal directive
# eg:
# location /private {
# internal;
# alias /path/to/media;
# }
if getattr(settings, "USE_X_ACCEL_REDIRECT", False):
response = HttpResponse()
response["Content-Type"] = ""
response["X-Accel-Redirect"] = f"/private/{file.name}"
else:
response = FileResponse(
open(file.path, "rb"), as_attachment=True
)
response["Content-Disposition"] = '{}; filename="{}"'.format(
disposition, smart_str(os.path.basename(file.path))
)
return response
raise Http404("File not found") raise Http404("File not found")