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

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

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

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

[`FileField`](/ja/2.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/2.1/ref/request-response/#django.http.HttpRequest.FILES) というディクショナリの中に受け取ります。このディクショナリには、キーと、それぞれのキーに対応するフォームの [`FileField`](/ja/2.1/ref/forms/fields/#django.forms.FileField) (または [`ImageField`](/ja/2.1/ref/forms/fields/#django.forms.ImageField) または他の [`FileField`](/ja/2.1/ref/forms/fields/#django.forms.FileField) のサブクラス) が格納されています。そのため、上のフォームから送信されたデータには、`request.FILES['file']` でアクセスすることができます。

ただし、[`request.FILES`](/ja/2.1/ref/request-response/#django.http.HttpRequest.FILES) にデータが格納されるのは、リクエストメソッドが `POST` で、かつリクエストをポストした `<form>` の属性に `enctype="multipart/form-data"` が設定されていた場合に限られることに注意してください。そうでない場合には、`request.FILES` は空のディクショナリになります。

ほとんどの場合、[Binding uploaded files to a form](/ja/2.1/ref/forms/api/#binding-uploaded-files) で説明されているように、`request` からフォームへデータを引き渡すだけでしょう。その場合、下記のようになります:

*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/2.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/2.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile) を読んでください。

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

[`FileField`](/ja/2.1/ref/models/fields/#django.db.models.FileField) を持つ [`Model`](/ja/2.1/ref/models/instances/#django.db.models.Model) 上のファイルを保存するときは、[`ModelForm`](/ja/2.1/topics/forms/modelforms/#django.forms.ModelForm) を使えば、このプロセスはとても簡単になります。この場合、ファイルオブジェクトは、`form.save()` を呼び出すだけで、対応する [`FileField`](/ja/2.1/ref/models/fields/#django.db.models.FileField) の [`upload_to`](/ja/2.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})
```

手動でオブジェクトを作成する場合には、[`request.FILES`](/ja/2.1/ref/request-response/#django.http.HttpRequest.FILES) 内のファイルオブジェクトを、モデルの file\_field 引数に指定するだけで大丈夫です。

```
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})
```

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

1 つのフォームフィールドで複数のファイルをアップロードしたい場合、フィールドのウィジェットの `multiple` HTML 属性をセットしてください:

*forms.py*

```python
from django import forms

class FileFieldForm(forms.Form):
    file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
```

そして、複数のファイルアップロードを扱うために、あなたの [`FormView`](/ja/2.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 FileFieldView(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)
        files = request.FILES.getlist('file_field')
        if form.is_valid():
            for f in files:
                ...  # Do something with each file.
            return self.form_valid(form)
        else:
            return self.form_invalid(form)
```

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

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

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

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

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

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

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

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

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

これらの特定の設定――2.5 MB だとか `/tmp` ディレクトリなど――は、単に「常識的なデフォルト」として設定されているだけなので、次のセクションで説明するように、自分でカスタマイズすることができます。

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

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

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

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

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

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

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

アップロードハンドラ全体を置き換えたい場合は、新しいリストを代入するだけでも構いません。

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

> **Note**
>
> アップロードハンドラは、`request.POST` や `request.FILES` にアクセスする *前に* のみ修正できます。処理が始まってからアップロードハンドラを修正しても無意味だからです。もし `request.POST` や `request.FILES` を読み込んだ後に `request.upload_handlers` を修正しようとしたならば、Django はエラーを投げます。
>
> したがって、アップロードハンドラの修正は、常にビューのできるだけ早い段階で行うようにするべきです。
>
> さらに、`request.POST` は、デフォルトで有効になっている [`CsrfViewMiddleware`](/ja/2.1/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware) によってアクセスされます。つまり、アップロードハンドラを変更できるようにするためには、ビュー上で [`csrf_exempt()`](/ja/2.1/ref/csrf/#django.views.decorators.csrf.csrf_exempt) を使う必要があります。それから、実際にそのリクエストを処理する関数上で、[`csrf_protect()`](/ja/2.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
> ```
