Как создать ссылку на скачивание Django - PullRequest
0 голосов
/ 28 января 2019

Я хотел бы защитить загружаемые файлы в моем проекте, но не знаю, как этого добиться.Каждый раз, когда вызов get_detail view вызывается, новая ссылка на скачивание должна генерироваться со сроком действия 60 минут и может быть только доступной.

models.py

class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(verbose_name="Post Title", max_length=25)
    content = models.TextField(verbose_name="Post Content", max_length=5000)
    tag = models.CharField(verbose_name="Tags/Meta - (sep. by comma)", max_length=50, blank=True)
    category = models.ForeignKey(Category, verbose_name="Category", on_delete=models.CASCADE, null=True)
    postattachment = fields.FileField(
        verbose_name="Post Attachment",
        blank=True,
        null=True,
        upload_to=get_file_path_user_uploads,
        validators=[file_extension_postattachment, file_size_postattachment]

    published_date = models.DateField(auto_now_add=True, null=True)


    def publish(self):
        self.published_date = timezone.now()
        self.save()

    class Meta:
        verbose_name = "Post"
        verbose_name_plural = "Post(s)"
        ordering = ['-title']

    def __str__(self):
        return self.title

views.py

def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    list_comments = Comment.objects.get_queryset().filter(post_id=pk).order_by('-pk')
    paginator = Paginator(list_comments, 10)
    page = request.GET.get('commentpage')
    comments = paginator.get_page(page)
    return render(request, 'MyProject/post_detail.html', {'post': post, 'comments': comments})

Если кто-томожет быть, есть некоторый пример практики, это было бы очень полезно.

Заранее спасибо

1 Ответ

0 голосов
/ 28 января 2019

Я не эксперт по Django, но я думаю, что этого нельзя достичь исключительно в Django.После того как ваш запрос был выполнен в Django, то есть вы успешно сгенерировали ссылку для загрузки для своего пользователя, вы не можете вернуться через 60 минут и сделать ее недействительной.Не чистым Django (исправьте меня!).

Другая причина блокировки заключается в том, что Django просто не предназначен для обслуживания файлов.Файлы (статические и мультимедийные) предназначены для обслуживания веб-сервером, установленным перед Django (apache / nginx / etc ...).Например, файл, сохраненный Django, может быть доступен по следующей ссылке: https://my-django-app.venom.com/media/my_file.jpg

Проблема здесь в том, что местоположение вашего файла легко угадать.Чтобы было сложнее угадать, вы должны поместить его в папку с длинной случайной строкой, например: https://my-django-app.venom.com/media/b926yqagf6qrzpyew7h3kghtejayxp/my_file.jpg.

Чтобы достичь такой функциональности, я вижу два пути (может быть десяткидругие альтернативы, но эти два сразу же приходят мне в голову):

Создание и удаление случайного пути

Чтобы сделать путь недействительным через 60 минут, вам придется выполнить следующие действия впорядок для каждого запроса файла:

  1. Генерирование случайной строки
  2. Создание папки с использованием сгенерированной случайной строки в качестве имени
  3. Скопируйте файл, который будет обслуживаться в этомпапка (оригинальная версия файла должна храниться за пределами вашей папки MEDIA для большей безопасности
  4. . Предоставьте пользователю ссылку для генерации
  5. . Зарегистрируйте этот URL-адрес где-нибудь и установите для него дату истечения срока действия.Например, через 60 минут после генерации (я бы создал для этого простую модель и сохранил бы ее в SQL)
  6. Запуск задания каждую минуту для сохраненных URL-адресов, и если срок его действия истек,удалите его папку из файловой системы

Чтобы выполнить 6-й шаг, вам нужно расширить приложение Django с помощью Celery.Используя Celery, вы можете легко планировать работу (Google для celery-beat).Это задание будет выполняться каждую минуту (или что вам нравится), запрашивать сохраненные URL за текущим временем и удалять папку случайных строк и ее содержимое из папки MEDIA в файловой системе.Celery очень прост, есть десятки хороших примеров, доступных онлайн.

Управление устаревшими ссылками за пределами Django с помощью сервера хранения объектов

Управлять просроченными ссылками на уровне инфраструктуры очень просто, сохраняяпользователь загружал содержимое в хранилище объектов, например, minio.Minio очень похож на Amazon S3, но с открытым исходным кодом и может быть размещен в вашем собственном помещении.Minio может генерировать ссылки для сохраненных файлов, и вы можете установить срок действия от 1 минуты до 1 недели.В Django все, что вам нужно сделать, это запросить ссылку на Minio и указать срок действия.Остальным управляет minio.

Для реализации этого подхода вам необходимо расширить API хранилища файлов Django (https://docs.djangoproject.com/en/2.1/ref/files/storage/) и использовать один из клиентов minio, написанных для Django. Я рекомендую django-minio-storage (https://github.com/py-pa/django-minio-storage).

Если вы выберете этот метод, вы можете полностью отделить Django от загруженного пользователем содержимого и перестать полагаться на файлы, обслуживающие ваш веб-сервер, из папки Django MEDIA.

Удачи!

Обновление:

Вот моя реализация хранилища minio в Django 2.x на основе пакета django-minio-storage. Я создал это относительно давно, и этоможет быть полон плохих практик и хакерских решений. Не стесняйтесь использовать его как справочную работу: https://gist.github.com/theriverman/db9025a22e0f3c40810bed5f12a139d8

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...