Django генерирование рандомных имён загруженным файлам FileField

В одном из моих проектов мне потребовалось реализовать загрузку пользовательских файлов через форму. Я использовал обычный FileField как советуют во всех туториалах, с стандартной конфигурацией. Пользователи загружали файлы, и все работало хорошо. Но затем я заметил проблему - делов в том что имя файла на сервере совпадало с именем файла которое загрузил пользователь. То есть, например если пользователь загружает картинку 1.png, то его картинка будет доступна по ссылке /uploads/1.png. Проблема этого подхода в том что в таких случаях имя файла можно будет просто перебрать и находить чужие файлы. Например, собрать огромный список стандартных названий файлов, и перебирать их в целях найти чужие файлы.

Чтобы исправить эту проблему нужно просто использовать случайные имена файлов. Но дело в том что по умолчанию FileField нигде не сохраняет оригинальное имя файла. Оригинальное имя файла придётся сохранять отдельным полем в моделях.

@csrf_exempt
@login_required
def upload_file(request, str):
    form = DashboardUserUploadAttachmentForm(request.POST, request.FILES)

    if form.is_valid():
        attachment = form.save(commit=False)
        attachment.filename = request.FILES['attachment'].name
        attachment.owner = request.user
        attachment.save()

        return JsonResponse({
            'status': 'ok'
        })
    else:
        return JsonResponse({'status': 'error', 'errors': form.errors})

Поэтому пришлось добавить логику забирания имени файла с запроса чтобы передавать имя файла модели отдельным полем.

def get_file_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (uuid.uuid4(), ext)
    return os.path.join('uploads/', filename)

class DashboardUserAttachments(models.Model):
    created_at = models.DateTimeField(auto_now=True)
    sent_at = models.DateTimeField(null=True, blank=True)
    attachment = models.FileField(upload_to=get_file_path)
    filename = models.CharField(max_length=128, default='')

    type_of_attachment = models.CharField(
        max_length=20,
        choices=ATTACHMENTS_TYPES
    )
    owner = models.ForeignKey(
        'DashboardUser',
        on_delete=models.CASCADE,
        related_name='user_attachments'
    )
    comment = models.TextField(default='')

После этого, каждый загруженный файл пользователей имел случайно сгенерированное имя файла. Но за тем на продакшене я столкнулся с другой проблемой: мы использовали cloudflare. А в нем максимальное тело запроса это не 100 мегабайт. Из-за этого наши пользователи начали сталкиватся с проблемами при загрузке файлов больше 100 мегабайт. Решение только 1 - убрать cloudflare для сервиса загрузки файлов. Но можно пойти более радикально и переписать всю логику загрузки файлов на чанковую. Это когда файл разбивается на кусочки на стороне клиента, и отправляется небольшими запросами на сервер, где потом этот файл соединяют в 1. Такой подход гораздо лучше потому что при чанковой загрузке можно иметь больший контроль над процессом загрузки. Например можно поставить загрузку на паузу, либо при потере соединения продолжить загрузку. Так что загружать файлы 1 запросом не стоит если вы собираетесь делать продакшен приложения, это нехорошая практика. Лучше сделать загрузку чанками.

Комментарии

  1. If you are interested in the demo play, that is out there right from the foyer . Just bear in mind that you can't 코인카지노 win real money on-line in free play mode. This fun-tastic 3D slot machine game is available at Casino.com where - surprise!

    ОтветитьУдалить

Отправить комментарий

Популярные сообщения из этого блога

DOS атака при помощи Python

Ведем телеграм канал через питон

Новый мощный скрипт для дудоса python 3