Можно ли поменять имя файла FileField во время загрузки / ссылки на FE? - PullRequest
0 голосов
/ 03 июля 2019

Я использую Django + DRF, чтобы позволить загружать / сохранять / обслуживать загруженные пользователем файлы активов. Мне нужно разрешить пользователям загружать загруженные ресурсы позже. После загрузки файла мне нужно md5-hash его настоящее имя и сохранить его в файловой системе с таким хэшем в качестве имени файла. Затем, когда пользователь хочет загрузить / просмотреть его в FE, скажем, он загрузил файл «cute_cat.jpg», я хочу, чтобы он получил файл с именем «cute_cat.jpg», а не 3c808e77fc1b0aee4435533690be458d (это одна проблема, другая один из них заключается в том, что браузер использует файлы без расширений как application / octet-stream, и я хочу, чтобы он отображал файлы «.jpg» (изначально) в виде изображений)

Мне кажется, что мне нужно вставить HTTP-заголовок с помощью 'Content-Disposition: attachment; filename = cute_cat.jpg '(я сохраняю реальное имя файла в БД) где-то на пути к Response () DRF, но я не уверен, в какой момент я должен это сделать, и даже если это возможно ... Я пробовал кучу вещей, в основном реализуя настраиваемые поля для сериализатора и вставляя туда пользовательский URL, но, очевидно, это не тот путь, потому что некуда вставлять заголовки в текстовый URL, и нет смысла пытаться вывести Запросить объект с заголовками в представлении API ...

Это моя модель:

def get_full_path(instance, filename):
  return '/'.join([
    instance.user.name,
    hashlib.md5(filename.encode()).hexdigest()
  ])

class CustomAsset(models.Model):
  file = models.FileField(blank=False, null=False, upload_to=get_full_path)
  real_file_name = models.CharField(max_length=255, blank=False, null=False)
  user = models.ForeignKey(...)

Ничего не переопределяется в представлении сериализатора / API.

Заранее большое спасибо.

1 Ответ

0 голосов
/ 03 июля 2019

Сначала вы должны понять в API, все, что вы можете вернуть, это URL.

Теперь браузер отвечает за форматирование файлов и управление типами контента. Здесь вам нужно будет управлять файлом через контроллер приложения. Когда вы возвращаете URL, вы возвращаете что-то вроде.

http://example.com/file/<md5> 

И этот URL при обращении обслуживает файл через контроллер с измененным заголовком расположения содержимого и возвращает файл в качестве ответа.

Простой пример будет выглядеть так:

В вашем urls.py, добавьте новый маршрут.

url(r'^file/(?P<identifier>[\w\d\-_]+)$', custom_file_server, name="custom_file_server"),

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

def custom_file_server(request, identifier):
    ## Get the file name from db by querying from identifier
    file_name = "abc.jpg"
    absolute_file_path = os.path.join(settings.BASE_DIR, "media/"+identifier)
    response = FileResponse(open(absolute_file_path, 'rb'))
    response['Content-Disposition'] = "attachment; filename={}".format(file_name)
    response['Content-Type'] = 'image/jpeg'
    return response

Приведенный выше код не проверен, но концепция остается такой. Дайте знать, если у вас появятся вопросы.

...