---
title: "ファイルのアップロード"
version: 4.1
locale: ja
source: https://docs.djangoproject.com/ja/4.1/topics/http/file-uploads/
canonical: https://djangodocs.dev/ja/4.1/topics/http/file-uploads/
---
# ファイルのアップロード

Django がファイルアップロードを扱うとき、ファイルデータは [`request.FILES`](/ja/4.1/ref/request-response/#django.http.HttpRequest.FILES) に格納されます (`request` についての詳細は [request and response objects](/ja/4.1/ref/request-response/) をご覧ください)。ここでは、ファイルがどのようにディスクとメモリに保管され、またどうやってデフォルトの動作を変更するかを説明します。

> **Warning**
>
> 信頼できないユーザーからコンテンツアップロードを許可する場合、セキュリティリスクが存在します！緩和策の詳細は、[ユーザーがアップロードしたコンテンツ](/ja/4.1/topics/security/#user-uploaded-content-security) のセキュリティガイドをご覧ください。

## ファイルのアップロードの基本

Consider a form containing a [`FileField`](/ja/4.1/ref/forms/fields/#django.forms.FileField):

*`forms.py`*

```python
from django import forms

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()
```

このフォームをハンドリングするビューは、ファイルのデータを [`request.FILES`](/ja/4.1/ref/request-response/#django.http.HttpRequest.FILES) というディクショナリの中に受け取ります。このディクショナリには、キーと、それぞれのキーに対応するフォームの [`FileField`](/ja/4.1/ref/forms/fields/#django.forms.FileField) (または [`ImageField`](/ja/4.1/ref/forms/fields/#django.forms.ImageField) または他の [`FileField`](/ja/4.1/ref/forms/fields/#django.forms.FileField) のサブクラス) が格納されています。そのため、上のフォームから送信されたデータには、`request.FILES['file']` でアクセスすることができます。

Note that [`request.FILES`](/ja/4.1/ref/request-response/#django.http.HttpRequest.FILES) will only
contain data if the request method was `POST`, at least one file field was
actually posted, and the `<form>` that posted the request has the attribute
`enctype="multipart/form-data"`. Otherwise, `request.FILES` will be empty.

Most of the time, you'll pass the file data from `request` into the form as
described in [Binding uploaded files to a form](/ja/4.1/ref/forms/api/#binding-uploaded-files). This would look something like:

*`views.py`*

```python
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm

# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})
```

ここで、[`request.FILES`](/ja/4.1/ref/request-response/#django.http.HttpRequest.FILES) をフォームのコンストラクタに渡す必要があることに注意してください。

アップロードされたファイルをハンドルする一般的な方法は、次のようになります。

```
def handle_uploaded_file(f):
    with open('some/file/name.txt', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)
```

`read()` を使う代わりに `UploadedFile.chunks()` でループすることで、大きなサイズのファイルがアップロードされた時にメモリが専有されることを防げます。

`UploadedFile` オブジェクトには、他にもいくつかのメソッドと属性があります。完全なリファレンスについては、[`UploadedFile`](/ja/4.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile) を読んでください。

### モデルを使用したアップロードファイルのハンドリング

[`FileField`](/ja/4.1/ref/models/fields/#django.db.models.FileField) を持つ [`Model`](/ja/4.1/ref/models/instances/#django.db.models.Model) 上のファイルを保存するときは、[`ModelForm`](/ja/4.1/topics/forms/modelforms/#django.forms.ModelForm) を使えば、このプロセスはとても簡単になります。この場合、ファイルオブジェクトは、`form.save()` を呼び出すだけで、対応する [`FileField`](/ja/4.1/ref/models/fields/#django.db.models.FileField) の [`upload_to`](/ja/4.1/ref/models/fields/#django.db.models.FileField.upload_to) 引数で指定した場所に保存されます。

```
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ModelFormWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = ModelFormWithFileField(request.POST, request.FILES)
        if form.is_valid():
            # file is saved
            form.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = ModelFormWithFileField()
    return render(request, 'upload.html', {'form': form})
```

If you are constructing an object manually, you can assign the file object from
[`request.FILES`](/ja/4.1/ref/request-response/#django.http.HttpRequest.FILES) to the file field in the
model:

```
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
from .models import ModelWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            instance = ModelWithFileField(file_field=request.FILES['file'])
            instance.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})
```

If you are constructing an object manually outside of a request, you can assign
a [`File`](/ja/4.1/ref/files/file/#django.core.files.File) like object to the
[`FileField`](/ja/4.1/ref/models/fields/#django.db.models.FileField):

```
from django.core.management.base import BaseCommand
from django.core.files.base import ContentFile

class MyCommand(BaseCommand):
    def handle(self, *args, **options):
        content_file = ContentFile(b'Hello world!', name='hello-world.txt')
        instance = ModelWithFileField(file_field=content_file)
        instance.save()
```

### 複数のファイルをアップロードする

If you want to upload multiple files using one form field, create a subclass
of the field's widget and set the `allow_multiple_selected` attribute on it
to `True`.

In order for such files to be all validated by your form (and have the value of
the field include them all), you will also have to subclass `FileField`. See
below for an example.

> **Multiple file field**
>
> Django is likely to have a proper multiple file field support at some point
> in the future.

*`forms.py`*

```python
from django import forms

class MultipleFileInput(forms.ClearableFileInput):
    allow_multiple_selected = True

class MultipleFileField(forms.FileField):
    def __init__(self, *args, **kwargs):
        kwargs.setdefault("widget", MultipleFileInput())
        super().__init__(*args, **kwargs)

    def clean(self, data, initial=None):
        single_file_clean = super().clean
        if isinstance(data, (list, tuple)):
            result = [single_file_clean(d, initial) for d in data]
        else:
            result = single_file_clean(data, initial)
        return result

class FileFieldForm(forms.Form):
    file_field = MultipleFileField()
```

そして、複数のファイルアップロードを扱うために、あなたの [`FormView`](/ja/4.1/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView) サブクラスの `post` メソッドをオーバーライドします:

*`views.py`*

```python
from django.views.generic.edit import FormView
from .forms import FileFieldForm

class FileFieldFormView(FormView):
    form_class = FileFieldForm
    template_name = 'upload.html'  # Replace with your template.
    success_url = '...'  # Replace with your URL or reverse().

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form):
        files = form.cleaned_data["file_field"]
        for f in files:
            ...  # Do something with each file.
        return super().form_valid()
```

> **Warning**
>
> This will allow you to handle multiple files at the form level only. Be
> aware that you cannot use it to put multiple files on a single model
> instance (in a single field), for example, even if the custom widget is used
> with a form field related to a model `FileField`.

> **Changed in Django 3.2.19**
>
> In previous versions, there was no support for the `allow_multiple_selected`
> class attribute, and users were advised to create the widget with the HTML
> attribute `multiple` set through the `attrs` argument. However, this
> caused validation of the form field to be applied only to the last file
> submitted, which could have adverse security implications.

## アップロードハンドラ

サイトのユーザがファイルをアップロードした時、Django はそのファイルのデータを *アップロードハンドラ (upload handler)* という、ファイルがアップロードされた時にデータをハンドリングするための小さなクラスへ渡します。アップロードハンドラは、初めに設定の [`FILE_UPLOAD_HANDLERS`](/ja/4.1/ref/settings/#std-setting-FILE_UPLOAD_HANDLERS) で定義されています。デフォルトでは次のようになっています。

```
["django.core.files.uploadhandler.MemoryFileUploadHandler",
 "django.core.files.uploadhandler.TemporaryFileUploadHandler"]
```

[`MemoryFileUploadHandler`](/ja/4.1/ref/files/uploads/#django.core.files.uploadhandler.MemoryFileUploadHandler) と [`TemporaryFileUploadHandler`](/ja/4.1/ref/files/uploads/#django.core.files.uploadhandler.TemporaryFileUploadHandler) はともに、Django でファイルがアップロードされた時のデフォルトの動作――小さなファイルはメモリ上に保存し、大きなファイルはディスクに保存する――を提供しています。

カスタマイズハンドラを書けば、Django がファイルをハンドリングする方法をカスタマイズすることができます。たとえば、カスタムハンドラを使うことで、ユーザレベルでのクオータを設定したり、データをその場で圧縮したり、プログレスバーを表示したり、あるいは、送られたデータをローカルに保存せずに、別のストレージに転送することさえ可能です。ハンドラをカスタマイズしたり、アップロード時の動作を完全に置き換えたりする方法については、詳しくは [アップロードハンドラをカスタマイズする](/ja/4.1/ref/files/uploads/#custom-upload-handlers) を読んでください。

### アップロードされたデータの保存場所

アップロードされたファイルを保存する時点で、そのデータはコンピュータ上のどこかに保存されているはずです。

デフォルトでは、アップロードファイルが 2.5 MB 未満ならば、Django はデータ全体をメモリ上に保持します。つまり、この場合にファイルを保存するというのは、メモリ上からデータを読み込んでディスクにファイルを書き込むだけなので、処理は短時間しかかかりません。

しかし、アップロードファイルのサイズが大きい場合、Django はアップロードファイルをシステムの一時ディレクトリ内に、一時ファイルとして保存します。Unix-like なプラットフォームなら、Django は `/tmp/tmpzfp6I6.upload` のようなファイルを作成すると考えて良いです。アップロードされたファイルが十分大きければ、Django がデータストリームをディスクに書き込むにつれ、このファイルのサイズが大きくなってゆくのを観察することができるでしょう。

These specifics -- 2.5 megabytes; `/tmp`; etc. -- are "reasonable defaults"
which can be customized as described in the next section.

### アップロードハンドラの動作の変更

Django のファイルアップロードの動作を制御するための設定がいくつかあります。詳しくは、 [File Upload Settings](/ja/4.1/ref/settings/#file-upload-settings) を参照してください。

### その場でアップロードハンドラを修正する

時として特定のビューが異なるアップロード動作を必要とすることがあります。このような場合には、`request.upload_handlers` を修正することで、1リクエストごとに、アップロードハンドラをオーバーライドすることが可能です。デフォルトでは、このリストには [`FILE_UPLOAD_HANDLERS`](/ja/4.1/ref/settings/#std-setting-FILE_UPLOAD_HANDLERS) の設定で指定したアップロードハンドラが入っていますが、このリストは自由に修正することができます。

たとえば、アップロードの進行状況を計算して、AJAX のウィジェットなどにフィードバックを返す `ProgressBarUploadHandler` というハンドラを作ったとしましょう。このハンドラを、次のようにアップロードハンドラのリストに追加します。

```
request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
```

この場合には、`list.append()` メソッドの代わりに `list.insert()` を使ったほうが良いでしょう。なぜなら、プログレスバーハンドラーは、他のハンドラの *前に* 実行する必要があるでしょうから。アップロードハンドラは、リストの前から順に処理されることに注意してください。

If you want to replace the upload handlers completely, you can assign a new
list:

```
request.upload_handlers = [ProgressBarUploadHandler(request)]
```

> **Note**
>
> アップロードハンドラは、`request.POST` や `request.FILES` にアクセスする *前に* のみ修正できます。処理が始まってからアップロードハンドラを修正しても無意味だからです。もし `request.POST` や `request.FILES` を読み込んだ後に `request.upload_handlers` を修正しようとしたならば、Django はエラーを投げます。
>
> したがって、アップロードハンドラの修正は、常にビューのできるだけ早い段階で行うようにするべきです。
>
> さらに、`request.POST` は、デフォルトで有効になっている [`CsrfViewMiddleware`](/ja/4.1/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware) によってアクセスされます。つまり、アップロードハンドラを変更できるようにするためには、ビュー上で [`csrf_exempt()`](/ja/4.1/ref/csrf/#django.views.decorators.csrf.csrf_exempt) を使う必要があります。それから、実際にそのリクエストを処理する関数上で、[`csrf_protect()`](/ja/4.1/ref/csrf/#django.views.decorators.csrf.csrf_protect) を使う必要があります。ハンドラは、CSRF チェックが終わる前にファイルアップロードの受け取りを開始する可能性があることに注意してください。以下はコードの例です:
>
> ```
> from django.views.decorators.csrf import csrf_exempt, csrf_protect
>
> @csrf_exempt
> def upload_file_view(request):
>     request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
>     return _upload_file_view(request)
>
> @csrf_protect
> def _upload_file_view(request):
>     ... # Process request
> ```
>
> If you are using a class-based view, you will need to use
> [`csrf_exempt()`](/ja/4.1/ref/csrf/#django.views.decorators.csrf.csrf_exempt) on its
> [`dispatch()`](/ja/4.1/ref/class-based-views/base/#django.views.generic.base.View.dispatch) method and
> [`csrf_protect()`](/ja/4.1/ref/csrf/#django.views.decorators.csrf.csrf_protect) on the method that
> actually processes the request. Example code:
>
> ```
> from django.utils.decorators import method_decorator
> from django.views import View
> from django.views.decorators.csrf import csrf_exempt, csrf_protect
>
> @method_decorator(csrf_exempt, name='dispatch')
> class UploadFileView(View):
>
>     def setup(self, request, *args, **kwargs):
>         request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
>         super().setup(request, *args, **kwargs)
>
>     @method_decorator(csrf_protect)
>     def post(self, request, *args, **kwargs):
>         ... # Process request
> ```
