Django 将文件上传到取决于 POST URI 的特定目录

Posted

技术标签:

【中文标题】Django 将文件上传到取决于 POST URI 的特定目录【英文标题】:Django upload file into specific directory that depends on the POST URI 【发布时间】:2011-01-17 15:35:41 【问题描述】:

我想将上传的文件存储到取决于 POST 请求的 URI 的特定目录中。也许,我还想将文件重命名为固定的名称(例如文件输入的名称),这样我就有一种简单的方法来 grep 文件系统等,也可以避免可能的安全问题。

在 Django 中首选的方法是什么?

编辑:我应该澄清一下,我可能有兴趣将其作为文件上传处理程序执行,以避免将大文件两次写入文件系统。

Edit2:我想可以将 tmp 文件“mv”到一个新位置。如果在同一个文件系统上,这是一个便宜的操作。

【问题讨论】:

移动临时文件没问题。 Django 会检查这个案例,如果它丢失了不会抱怨:code.djangoproject.com/browser/django/trunk/django/core/files/… 【参考方案1】:

修复了 olooney 示例。它现在正在工作

@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)

【讨论】:

我不知道 ContentFile(request.FILES['file'].read()) 函数的来源。 从 django.core.files.base 导入内容文件【参考方案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 之外:

    扩展 TemporaryUploadedFile 并覆盖 init() 以通过不同的目录传递给 NamedTemporaryFile。它可以使用try mkdir,除了我上面显示的pass。

    扩展 TemporaryFileUploadHandler 并覆盖 new_file() 以使用上述类。

    还扩展 init() 以接受您希望文件夹所在的目录。

    动态添加请求处理程序,通过由 URL 确定的目录:

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

虽然不简单,但它仍然比从头开始编写处理程序更容易:特别是,您不必编写一行容易出错的缓冲读取。第 3 步和第 4 步是必要的,因为 FileUploadHandlers 默认不传递请求信息,我相信,所以如果你想以某种方式使用 URL,你必须单独告诉它。

我真的不建议为此编写自定义 FileUploadHandler。这真的混合了责任层。相对于通过 Internet 上传文件的速度,进行本地文件复制是微不足道的。如果文件很小,Django 只会将其保存在内存中,而不会将其写入临时文件。我有一种不好的预感,你会得到所有这些工作并发现你甚至无法衡量性能差异。

【讨论】:

当然,我正在寻找与 django.core.files.uploadhandler.TemporaryFileUploadHandler 无关的东西 好的。我会把它作为 the 的答案。我也有同样的想法,但是,对 Django 很陌生,我想和某人核实一下。顺便说一句,ProgressBarUploadHandler 是从哪里来的?我猜,从某个地方复制粘贴?很公平。感谢您为回答这个问题所做的努力。 虽然,不过,我真的希望对此进行更多讨论。例如,应该使用 django/core/files/storage.py 中的东西吗?这是关于什么的? 代码不工作。错误:AttributeError: 'file' object has no attribute 'chunks' 导入你的文件from .forms import UploadFileForm from somewhere import handle_uploaded_file

以上是关于Django 将文件上传到取决于 POST URI 的特定目录的主要内容,如果未能解决你的问题,请参考以下文章

Django - POST请求后将文件下载到客户端

上传文件 POST url 在部署时引发 404

django实现文件上传到服务器

上传文件时操作不允许错误 DJango

有没有办法在 nginx 上使用 django 上传一个非常大的文件?

在 Flutter 中上传带有 http.post 和注册表单的图像?