"""Storage-backed private media responses; callers MUST authorize the resource.""" import mimetypes from pathlib import Path from urllib.parse import quote from django.conf import settings from django.http import FileResponse, Http404, HttpResponse from django.utils.http import content_disposition_header def protected_file_response( attachment, *, filename, storage_directory, internal_prefix, use_x_accel=False, as_attachment=True, ): local_path = None if use_x_accel: try: local_path = attachment.path except NotImplementedError: pass if local_path is not None: try: root = (Path(settings.MEDIA_ROOT) / storage_directory).resolve(strict=True) path = Path(local_path).resolve(strict=True) relative = path.relative_to(root) if not path.is_file(): raise ValueError("not a file") except (OSError, ValueError) as exc: raise Http404("Файл недоступен") from exc response = HttpResponse( content_type=mimetypes.guess_type(filename)[0] or "application/octet-stream" ) response["X-Accel-Redirect"] = internal_prefix + quote( relative.as_posix(), safe="/" ) response["Content-Disposition"] = content_disposition_header( as_attachment, filename ) else: response = FileResponse( attachment.open("rb"), as_attachment=as_attachment, filename=filename ) response["Cache-Control"] = "private, no-store" response["X-Content-Type-Options"] = "nosniff" response["Content-Security-Policy"] = "sandbox" return response