{"title":"文件上传","version":"2.1","locale":"zh-hans","docname":"topics/http/file-uploads","url":"/zh-hans/2.1/topics/http/file-uploads/","canonical":"https://djangodocs.dev/zh-hans/2.1/topics/http/file-uploads/","summary":"Django处理文件上传时, 文件最终会位于:attr:request.FILES <django.http.HttpRequest.FILES> (想了解更多关于``request`` 对象的信息请阅读 request and response…","html":"<h1>文件上传<a class=\"heading-anchor\" href=\"#file-uploads\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django处理文件上传时, 文件最终会位于:attr:request.FILES &lt;django.http.HttpRequest.FILES&gt; (想了解更多关于``request`` 对象的信息请阅读  <span class=\"xref std std-doc\">request and response objects 1</span>) 。本文档主要介绍文件是如何存储在硬盘和内存中的，以及如何定制默认行为。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>如果接收不受信任的用户的上传会有安全隐患， 请阅读 :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>user-uploaded-content-security`获取详情.</p>\n</aside>\n<section id=\"basic-file-uploads\">\n<h2>简单文件上传<a class=\"heading-anchor\" href=\"#basic-file-uploads\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>考虑使用一个简单的表单，表单中包含一个:class:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>~django.forms.FileField`字段:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">forms.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> forms\n\n<span class=\"k\">class</span> <span class=\"nc\">UploadFileForm</span><span class=\"p\">(</span>forms<span class=\"o\">.</span>Form<span class=\"p\">):</span>\n    title <span class=\"o\">=</span> forms<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">50</span><span class=\"p\">)</span>\n    file <span class=\"o\">=</span> forms<span class=\"o\">.</span>FileField<span class=\"p\">()</span>\n</code></pre></figure>\n<p>处理这个表单的视图将通过:attr:request.FILES &lt;django.http.HttpRequest.FILES&gt;`获取到文件数据, attr:`request.FILES &lt;django.http.HttpRequest.FILES&gt;`是包含了表单中每个 :class:`~django.forms.FileField (还有 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/forms/fields/#django.forms.ImageField\" title=\"django.forms.ImageField\"><code class=\"xref py py-class docutils literal notranslate\">ImageField</code></a>, 以及其他:class:~django.forms.FileField 的子类)键值的字典 。所以 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>数据可以通过`request.FILES['file']``获取到。</p>\n<p>请注意只有在请求是通过 <code class=\"docutils literal notranslate\">POST</code> 提交且提交的  <code class=\"docutils literal notranslate\">&lt;form&gt;</code> 表单有 <code class=\"docutils literal notranslate\">enctype=&quot;multipart/form-data&quot;</code> 属性的时候，<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpRequest.FILES\" title=\"django.http.HttpRequest.FILES\"><code class=\"xref py py-attr docutils literal notranslate\">request.FILES</code></a>  才会包含文件数据，否则的话， <code class=\"docutils literal notranslate\">request.FILES</code> 是空的。</p>\n<p>绝大多数的情况下，你只需要像 <span class=\"xref std std-ref\">binding-uploaded-files`中所述将文件数据从``request`</span> 传入给 表单，示例如下：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">views.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">.forms</span> <span class=\"kn\">import</span> UploadFileForm\n\n<span class=\"c1\"># Imaginary function to handle an uploaded file.</span>\n<span class=\"kn\">from</span> <span class=\"nn\">somewhere</span> <span class=\"kn\">import</span> handle_uploaded_file\n\n<span class=\"k\">def</span> <span class=\"nf\">upload_file</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>method <span class=\"o\">==</span> <span class=\"s1\">&#39;POST&#39;</span><span class=\"p\">:</span>\n        form <span class=\"o\">=</span> UploadFileForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">,</span> request<span class=\"o\">.</span>FILES<span class=\"p\">)</span>\n        <span class=\"k\">if</span> form<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            handle_uploaded_file<span class=\"p\">(</span>request<span class=\"o\">.</span>FILES<span class=\"p\">[</span><span class=\"s1\">&#39;file&#39;</span><span class=\"p\">])</span>\n            <span class=\"k\">return</span> HttpResponseRedirect<span class=\"p\">(</span><span class=\"s1\">&#39;/success/url/&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        form <span class=\"o\">=</span> UploadFileForm<span class=\"p\">()</span>\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s1\">&#39;upload.html&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;form&#39;</span><span class=\"p\">:</span> form<span class=\"p\">})</span>\n</code></pre></figure>\n<p>注意我们必须将 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpRequest.FILES\" title=\"django.http.HttpRequest.FILES\"><code class=\"xref py py-attr docutils literal notranslate\">request.FILES</code></a> 传入到表单的\n构造方法中，只有这样文件数据才能绑定到表单中。</p>\n<p>我们通常可能像这样处理上传文件：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">handle_uploaded_file</span><span class=\"p\">(</span>f<span class=\"p\">):</span>\n    <span class=\"k\">with</span> <span class=\"nb\">open</span><span class=\"p\">(</span><span class=\"s1\">&#39;some/file/name.txt&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;wb+&#39;</span><span class=\"p\">)</span> <span class=\"k\">as</span> destination<span class=\"p\">:</span>\n        <span class=\"k\">for</span> chunk <span class=\"ow\">in</span> f<span class=\"o\">.</span>chunks<span class=\"p\">():</span>\n            destination<span class=\"o\">.</span>write<span class=\"p\">(</span>chunk<span class=\"p\">)</span>\n</code></pre></div>\n<p>使用 <code class=\"docutils literal notranslate\">UploadedFile.chunks()</code> 而不是 <code class=\"docutils literal notranslate\">read()</code> 是为了确保即使是大文件又不会将我们系统的内存占满。</p>\n<p>There are a few other methods and attributes available on <code class=\"docutils literal notranslate\">UploadedFile</code>\nobjects; see <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile\" title=\"django.core.files.uploadedfile.UploadedFile\"><code class=\"xref py py-class docutils literal notranslate\">UploadedFile</code></a> for a complete reference.</p>\n<section id=\"handling-uploaded-files-with-a-model\">\n<h3>通过模型来处理上传的文件<a class=\"heading-anchor\" href=\"#handling-uploaded-files-with-a-model\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If you're saving a file on a <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/models/instances/#django.db.models.Model\" title=\"django.db.models.Model\"><code class=\"xref py py-class docutils literal notranslate\">Model</code></a> with a\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/models/fields/#django.db.models.FileField\" title=\"django.db.models.FileField\"><code class=\"xref py py-class docutils literal notranslate\">FileField</code></a>, using a <a class=\"reference internal\" href=\"/zh-hans/2.1/topics/forms/modelforms/#django.forms.ModelForm\" title=\"django.forms.ModelForm\"><code class=\"xref py py-class docutils literal notranslate\">ModelForm</code></a>\nmakes this process much easier. The file object will be saved to the location\nspecified by the <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/models/fields/#django.db.models.FileField.upload_to\" title=\"django.db.models.FileField.upload_to\"><code class=\"xref py py-attr docutils literal notranslate\">upload_to</code></a> argument of the\ncorresponding <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/models/fields/#django.db.models.FileField\" title=\"django.db.models.FileField\"><code class=\"xref py py-class docutils literal notranslate\">FileField</code></a> when calling\n<code class=\"docutils literal notranslate\">form.save()</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">.forms</span> <span class=\"kn\">import</span> ModelFormWithFileField\n\n<span class=\"k\">def</span> <span class=\"nf\">upload_file</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>method <span class=\"o\">==</span> <span class=\"s1\">&#39;POST&#39;</span><span class=\"p\">:</span>\n        form <span class=\"o\">=</span> ModelFormWithFileField<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">,</span> request<span class=\"o\">.</span>FILES<span class=\"p\">)</span>\n        <span class=\"k\">if</span> form<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            <span class=\"c1\"># file is saved</span>\n            form<span class=\"o\">.</span>save<span class=\"p\">()</span>\n            <span class=\"k\">return</span> HttpResponseRedirect<span class=\"p\">(</span><span class=\"s1\">&#39;/success/url/&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        form <span class=\"o\">=</span> ModelFormWithFileField<span class=\"p\">()</span>\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s1\">&#39;upload.html&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;form&#39;</span><span class=\"p\">:</span> form<span class=\"p\">})</span>\n</code></pre></div>\n<p>If you are constructing an object manually, you can simply assign the file\nobject from <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.HttpRequest.FILES\" title=\"django.http.HttpRequest.FILES\"><code class=\"xref py py-attr docutils literal notranslate\">request.FILES</code></a> to the file\nfield in the model:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">.forms</span> <span class=\"kn\">import</span> UploadFileForm\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> ModelWithFileField\n\n<span class=\"k\">def</span> <span class=\"nf\">upload_file</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>method <span class=\"o\">==</span> <span class=\"s1\">&#39;POST&#39;</span><span class=\"p\">:</span>\n        form <span class=\"o\">=</span> UploadFileForm<span class=\"p\">(</span>request<span class=\"o\">.</span>POST<span class=\"p\">,</span> request<span class=\"o\">.</span>FILES<span class=\"p\">)</span>\n        <span class=\"k\">if</span> form<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            instance <span class=\"o\">=</span> ModelWithFileField<span class=\"p\">(</span>file_field<span class=\"o\">=</span>request<span class=\"o\">.</span>FILES<span class=\"p\">[</span><span class=\"s1\">&#39;file&#39;</span><span class=\"p\">])</span>\n            instance<span class=\"o\">.</span>save<span class=\"p\">()</span>\n            <span class=\"k\">return</span> HttpResponseRedirect<span class=\"p\">(</span><span class=\"s1\">&#39;/success/url/&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        form <span class=\"o\">=</span> UploadFileForm<span class=\"p\">()</span>\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s1\">&#39;upload.html&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;form&#39;</span><span class=\"p\">:</span> form<span class=\"p\">})</span>\n</code></pre></div>\n</section>\n<section id=\"uploading-multiple-files\">\n<h3>Uploading multiple files<a class=\"heading-anchor\" href=\"#uploading-multiple-files\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If you want to upload multiple files using one form field, set the <code class=\"docutils literal notranslate\">multiple</code>\nHTML attribute of field's widget:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">forms.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> forms\n\n<span class=\"k\">class</span> <span class=\"nc\">FileFieldForm</span><span class=\"p\">(</span>forms<span class=\"o\">.</span>Form<span class=\"p\">):</span>\n    file_field <span class=\"o\">=</span> forms<span class=\"o\">.</span>FileField<span class=\"p\">(</span>widget<span class=\"o\">=</span>forms<span class=\"o\">.</span>ClearableFileInput<span class=\"p\">(</span>attrs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;multiple&#39;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">}))</span>\n</code></pre></figure>\n<p>Then override the <code class=\"docutils literal notranslate\">post</code> method of your\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView\" title=\"django.views.generic.edit.FormView\"><code class=\"xref py py-class docutils literal notranslate\">FormView</code></a> subclass to handle multiple file\nuploads:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">views.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.views.generic.edit</span> <span class=\"kn\">import</span> FormView\n<span class=\"kn\">from</span> <span class=\"nn\">.forms</span> <span class=\"kn\">import</span> FileFieldForm\n\n<span class=\"k\">class</span> <span class=\"nc\">FileFieldView</span><span class=\"p\">(</span>FormView<span class=\"p\">):</span>\n    form_class <span class=\"o\">=</span> FileFieldForm\n    template_name <span class=\"o\">=</span> <span class=\"s1\">&#39;upload.html&#39;</span>  <span class=\"c1\"># Replace with your template.</span>\n    success_url <span class=\"o\">=</span> <span class=\"s1\">&#39;...&#39;</span>  <span class=\"c1\"># Replace with your URL or reverse().</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> request<span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n        form_class <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>get_form_class<span class=\"p\">()</span>\n        form <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>get_form<span class=\"p\">(</span>form_class<span class=\"p\">)</span>\n        files <span class=\"o\">=</span> request<span class=\"o\">.</span>FILES<span class=\"o\">.</span>getlist<span class=\"p\">(</span><span class=\"s1\">&#39;file_field&#39;</span><span class=\"p\">)</span>\n        <span class=\"k\">if</span> form<span class=\"o\">.</span>is_valid<span class=\"p\">():</span>\n            <span class=\"k\">for</span> f <span class=\"ow\">in</span> files<span class=\"p\">:</span>\n                <span class=\"o\">...</span>  <span class=\"c1\"># Do something with each file.</span>\n            <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span>form_valid<span class=\"p\">(</span>form<span class=\"p\">)</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span>form_invalid<span class=\"p\">(</span>form<span class=\"p\">)</span>\n</code></pre></figure>\n</section>\n</section>\n<section id=\"upload-handlers\">\n<h2>Upload Handlers<a class=\"heading-anchor\" href=\"#upload-handlers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>When a user uploads a file, Django passes off the file data to an <em>upload\nhandler</em> -- a small class that handles file data as it gets uploaded. Upload\nhandlers are initially defined in the <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-FILE_UPLOAD_HANDLERS\"><code class=\"xref std std-setting docutils literal notranslate\">FILE_UPLOAD_HANDLERS</code></a> setting,\nwhich defaults to:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"p\">[</span><span class=\"s2\">&quot;django.core.files.uploadhandler.MemoryFileUploadHandler&quot;</span><span class=\"p\">,</span>\n <span class=\"s2\">&quot;django.core.files.uploadhandler.TemporaryFileUploadHandler&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>Together <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/files/uploads/#django.core.files.uploadhandler.MemoryFileUploadHandler\" title=\"django.core.files.uploadhandler.MemoryFileUploadHandler\"><code class=\"xref py py-class docutils literal notranslate\">MemoryFileUploadHandler</code></a> and\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/files/uploads/#django.core.files.uploadhandler.TemporaryFileUploadHandler\" title=\"django.core.files.uploadhandler.TemporaryFileUploadHandler\"><code class=\"xref py py-class docutils literal notranslate\">TemporaryFileUploadHandler</code></a> provide Django's default file upload\nbehavior of reading small files into memory and large ones onto disk.</p>\n<p>You can write custom handlers that customize how Django handles files. You\ncould, for example, use custom handlers to enforce user-level quotas, compress\ndata on the fly, render progress bars, and even send data to another storage\nlocation directly without storing it locally. See <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/files/uploads/#custom-upload-handlers\"><span class=\"std std-ref\">Writing custom upload handlers</span></a>\nfor details on how you can customize or completely replace upload behavior.</p>\n<section id=\"where-uploaded-data-is-stored\">\n<h3>Where uploaded data is stored<a class=\"heading-anchor\" href=\"#where-uploaded-data-is-stored\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Before you save uploaded files, the data needs to be stored somewhere.</p>\n<p>By default, if an uploaded file is smaller than 2.5 megabytes, Django will hold\nthe entire contents of the upload in memory. This means that saving the file\ninvolves only a read from memory and a write to disk and thus is very fast.</p>\n<p>However, if an uploaded file is too large, Django will write the uploaded file\nto a temporary file stored in your system's temporary directory. On a Unix-like\nplatform this means you can expect Django to generate a file called something\nlike <code class=\"docutils literal notranslate\">/tmp/tmpzfp6I6.upload</code>. If an upload is large enough, you can watch this\nfile grow in size as Django streams the data onto disk.</p>\n<p>These specifics -- 2.5 megabytes; <code class=\"docutils literal notranslate\">/tmp</code>; etc. -- are simply &quot;reasonable\ndefaults&quot; which can be customized as described in the next section.</p>\n</section>\n<section id=\"changing-upload-handler-behavior\">\n<h3>Changing upload handler behavior<a class=\"heading-anchor\" href=\"#changing-upload-handler-behavior\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>There are a few settings which control Django's file upload behavior. See\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#file-upload-settings\"><span class=\"std std-ref\">File Upload Settings</span></a> for details.</p>\n</section>\n<section id=\"modifying-upload-handlers-on-the-fly\">\n<span id=\"id1\"></span><h3>Modifying upload handlers on the fly<a class=\"heading-anchor\" href=\"#modifying-upload-handlers-on-the-fly\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Sometimes particular views require different upload behavior. In these cases,\nyou can override upload handlers on a per-request basis by modifying\n<code class=\"docutils literal notranslate\">request.upload_handlers</code>. By default, this list will contain the upload\nhandlers given by <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-FILE_UPLOAD_HANDLERS\"><code class=\"xref std std-setting docutils literal notranslate\">FILE_UPLOAD_HANDLERS</code></a>, but you can modify the list\nas you would any other list.</p>\n<p>For instance, suppose you've written a <code class=\"docutils literal notranslate\">ProgressBarUploadHandler</code> that\nprovides feedback on upload progress to some sort of AJAX widget. You'd add this\nhandler to your upload handlers like this:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>request<span class=\"o\">.</span>upload_handlers<span class=\"o\">.</span>insert<span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"p\">,</span> ProgressBarUploadHandler<span class=\"p\">(</span>request<span class=\"p\">))</span>\n</code></pre></div>\n<p>You'd probably want to use <code class=\"docutils literal notranslate\">list.insert()</code> in this case (instead of\n<code class=\"docutils literal notranslate\">append()</code>) because a progress bar handler would need to run <em>before</em> any\nother handlers. Remember, the upload handlers are processed in order.</p>\n<p>If you want to replace the upload handlers completely, you can just assign a new\nlist:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>request<span class=\"o\">.</span>upload_handlers <span class=\"o\">=</span> <span class=\"p\">[</span>ProgressBarUploadHandler<span class=\"p\">(</span>request<span class=\"p\">)]</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>You can only modify upload handlers <em>before</em> accessing\n<code class=\"docutils literal notranslate\">request.POST</code> or <code class=\"docutils literal notranslate\">request.FILES</code> -- it doesn't make sense to\nchange upload handlers after upload handling has already\nstarted. If you try to modify <code class=\"docutils literal notranslate\">request.upload_handlers</code> after\nreading from <code class=\"docutils literal notranslate\">request.POST</code> or <code class=\"docutils literal notranslate\">request.FILES</code> Django will\nthrow an error.</p>\n<p>Thus, you should always modify uploading handlers as early in your view as\npossible.</p>\n<p>Also, <code class=\"docutils literal notranslate\">request.POST</code> is accessed by\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware\" title=\"django.middleware.csrf.CsrfViewMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">CsrfViewMiddleware</code></a> which is enabled by\ndefault. This means you will need to use\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/csrf/#django.views.decorators.csrf.csrf_exempt\" title=\"django.views.decorators.csrf.csrf_exempt\"><code class=\"xref py py-func docutils literal notranslate\">csrf_exempt()</code></a> on your view to allow you\nto change the upload handlers.  You will then need to use\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/csrf/#django.views.decorators.csrf.csrf_protect\" title=\"django.views.decorators.csrf.csrf_protect\"><code class=\"xref py py-func docutils literal notranslate\">csrf_protect()</code></a> on the function that\nactually processes the request.  Note that this means that the handlers may\nstart receiving the file upload before the CSRF checks have been done.\nExample code:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.views.decorators.csrf</span> <span class=\"kn\">import</span> csrf_exempt<span class=\"p\">,</span> csrf_protect\n\n<span class=\"nd\">@csrf_exempt</span>\n<span class=\"k\">def</span> <span class=\"nf\">upload_file_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    request<span class=\"o\">.</span>upload_handlers<span class=\"o\">.</span>insert<span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"p\">,</span> ProgressBarUploadHandler<span class=\"p\">(</span>request<span class=\"p\">))</span>\n    <span class=\"k\">return</span> _upload_file_view<span class=\"p\">(</span>request<span class=\"p\">)</span>\n\n<span class=\"nd\">@csrf_protect</span>\n<span class=\"k\">def</span> <span class=\"nf\">_upload_file_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"o\">...</span> <span class=\"c1\"># Process request</span>\n</code></pre></div>\n</aside>\n</section>\n</section>","rootId":"file-uploads","toc":[{"title":"简单文件上传","anchor":"basic-file-uploads","children":[{"title":"通过模型来处理上传的文件","anchor":"handling-uploaded-files-with-a-model","children":[]},{"title":"Uploading multiple files","anchor":"uploading-multiple-files","children":[]}]},{"title":"Upload Handlers","anchor":"upload-handlers","children":[{"title":"Where uploaded data is stored","anchor":"where-uploaded-data-is-stored","children":[]},{"title":"Changing upload handler behavior","anchor":"changing-upload-handler-behavior","children":[]},{"title":"Modifying upload handlers on the fly","anchor":"modifying-upload-handlers-on-the-fly","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Using Django","url":"/zh-hans/2.1/topics/"},{"docname":"topics/http/index","title":"处理 HTTP 请求","url":"/zh-hans/2.1/topics/http/"}],"prev":{"docname":"topics/http/decorators","title":"View decorators","url":"/zh-hans/2.1/topics/http/decorators/"},"next":{"docname":"topics/http/shortcuts","title":"Django快捷函数","url":"/zh-hans/2.1/topics/http/shortcuts/"},"formats":{"html":"/zh-hans/2.1/topics/http/file-uploads/","markdown":"/zh-hans/2.1/topics/http/file-uploads.md","json":"/zh-hans/2.1/topics/http/file-uploads.json"},"source":"https://github.com/django/django/blob/stable/2.1.x/docs/topics/http/file-uploads.txt","official":"https://docs.djangoproject.com/zh-hans/2.1/topics/http/file-uploads/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}