Django загружает файл в определенный каталог, который зависит от POST URI

Я хотел бы хранить загруженные файлы в определенном каталоге, который зависит от URI запроса POST. Возможно, я также хотел бы переименовать файл во что-то фиксированное (например, имя входного файла), чтобы у меня был простой способ поиска файловой системы и т. д., а также чтобы избежать возможных проблем с безопасностью.

Каков предпочтительный способ сделать это в Django?

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

Edit2: я полагаю, что можно просто «mv» файл tmp в новое место. Это дешевая операция, если в той же файловой системе.


person kmt    schedule 16.02.2010    source источник
comment
перемещение временного файла в порядке. Django проверяет этот случай и не жалуется, если он пропал: code.djangoproject.com/browser/django/trunk/django/core/files/   -  person olooney    schedule 17.02.2010


Ответы (2)


Django дает вам полный контроль над тем, где (и если) вы сохраняете файлы. См.: http://docs.djangoproject.com/en/dev/topics/http/file-uploads/

В приведенном ниже примере показано, как объединить URL-адрес и имя загруженного файла и записать файл на диск:

def upload(request):
    folder = request.path.replace("/", "_")
    uploaded_filename = request.FILES['file'].name

    # create the folder if it doesn't exist.
    try:
        os.mkdir(os.path.join(BASE_PATH, folder))
    except:
        pass

    # save the uploaded file inside that folder.
    full_filename = os.path.join(BASE_PATH, folder, uploaded_filename)
    fout = open(full_filename, 'wb+')
    # Iterate through the chunks.
    for chunk in fout.chunks():
        fout.write(chunk)
    fout.close()

Изменить: как это сделать с помощью FileUploadHandler? Он прослеживается по коду, и кажется, что вам нужно сделать четыре вещи, чтобы переназначить TemporaryFileUploadHandler для сохранения вне FILE_UPLOAD_TEMP_DIR:

  1. расширить TemporaryUploadedFile и переопределить init() для перехода через другой каталог к ​​NamedTemporaryFile. Он может использовать команду try mkdir, за исключением прохода, показанного выше.

  2. расширить TemporaryFileUploadHandler и переопределить new_file( ) для использования вышеуказанного класса.

  3. также расширьте init(), чтобы принять каталог, в который вы хотите поместить папку.

  4. Динамически добавьте обработчик запроса, проходящий через каталог, определенный из URL-адреса:

    request.upload_handlers = [ProgressBarUploadHandler (request.path.replace ('/', '_')]

Хотя это нетривиально, это все же проще, чем писать обработчик с нуля: в частности, вам не придется писать ни одной строки подверженного ошибкам чтения из буфера. Шаги 3 и 4 необходимы, потому что FileUploadHandlers по умолчанию не передают информацию о запросе, я полагаю, поэтому вам придется указать это отдельно, если вы хотите каким-то образом использовать URL-адрес.

Я не могу рекомендовать писать собственный FileUploadHandler для этого. Это действительно смешение уровней ответственности. По сравнению со скоростью загрузки файла через Интернет локальная копия файла не имеет значения. А если файл небольшой, Django просто сохранит его в памяти, не записывая во временный файл. У меня плохое предчувствие, что вы все это заработаете и обнаружите, что даже не можете измерить разницу в производительности.

person olooney    schedule 17.02.2010
comment
Конечно, я искал что-то не лишнее с django.core.files.uploadhandler.TemporaryFileUploadHandler. - person kmt; 17.02.2010
comment
Хорошо. Я приму это как ответ. Я думал в том же духе, но, будучи новичком в Django, хотел с кем-нибудь посоветоваться. Кстати, откуда взялся ProgressBarUploadHandler? Я так понимаю, копипаст откуда-то? Справедливо. Я ценю усилия ответить на этот вопрос. - person kmt; 17.02.2010
comment
Хотя, с другой стороны, я действительно хотел бы еще немного обсудить это. Например, следует ли использовать материал из django/core/files/storage.py? О чем это? - person kmt; 17.02.2010
comment
код не работает. Ошибка: AttributeError: 'file' object has no attribute 'chunks' - person Philip007; 27.05.2013
comment
импортировать это ваши файлыfrom .forms import UploadFileForm from somewhere import handle_uploaded_file - person bob marti; 07.03.2017

Исправлен пример looney. Это работает сейчас

@csrf_exempt
def upload_video_file(request):
    folder = 'tmp_dir2/' #request.path.replace("/", "_")
    uploaded_filename = request.FILES['file'].name
    BASE_PATH = '/home/'
    # create the folder if it doesn't exist.
    try:
        os.mkdir(os.path.join(BASE_PATH, folder))
    except:
        pass

    # save the uploaded file inside that folder.
    full_filename = os.path.join(BASE_PATH, folder, uploaded_filename)
    fout = open(full_filename, 'wb+')

    file_content = ContentFile( request.FILES['file'].read() )

    try:
        # Iterate through the chunks.
        for chunk in file_content.chunks():
            fout.write(chunk)
        fout.close()
        html = "<html><body>SAVED</body></html>"
        return HttpResponse(html)
    except:
        html = "<html><body>NOT SAVED</body></html>"
        return HttpResponse(html)
person user2455668    schedule 30.04.2014
comment
я не понимаю, откуда берется функция ContentFile( request.FILES['file'].read() ). - person Maurice Elagu; 05.11.2015
comment
из django.core.files.base импортировать ContentFile - person user2455668; 11.11.2015