---
title: "管理文件"
version: 4.2
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/4.2/topics/files/
canonical: https://djangodocs.dev/zh-hans/4.2/topics/files/
---
# 管理文件

这个文档描述 Django 文件访问用于文件的 API，例如用户上传的文件。较底层的API足够通用，你可以为其他目的来使用它们。如果你想处理 "static files" (JS, CSS, etc.)，可以查看 [如何管理静态文件（如图片、JavaScript、CSS）](/zh-hans/4.2/howto/static-files/) 。

默认情况下，Django 使用 [`MEDIA_ROOT`](/zh-hans/4.2/ref/settings/#std-setting-MEDIA_ROOT) 和 [`MEDIA_URL`](/zh-hans/4.2/ref/settings/#std-setting-MEDIA_URL) 设置本地存储。下面的例子假设你在使用这些默认设置。

不过，Django 提供编写自定义 [file storage systems](#file-storage) 的方法，允许你完全自定义 Django 存储文件的位置和方式。这篇文档的后半部分描述了存储系统的工作方式。

## 在模型中使用文件

当你使用 [`FileField`](/zh-hans/4.2/ref/models/fields/#django.db.models.FileField) 或 [`ImageField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ImageField) 时，Django 提供了一组处理文件的API。

考虑下面的模型，使用 [`ImageField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ImageField) 来存储照片：

```
from django.db import models

class Car(models.Model):
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    photo = models.ImageField(upload_to="cars")
    specs = models.FileField(upload_to="specs")
```

任何 `Car` 实例都将有一个 `photo` 属性，您可以使用它来获取附加照片的详细信息：

```pycon
>>> car = Car.objects.get(name="57 Chevy")
>>> car.photo
<ImageFieldFile: cars/chevy.jpg>
>>> car.photo.name
'cars/chevy.jpg'
>>> car.photo.path
'/media/cars/chevy.jpg'
>>> car.photo.url
'http://media.example.com/cars/chevy.jpg'
```

`car.photo` 是一个 `File` 对象，这意味着它拥有下面所描述的所有方法和属性。

> **Note**
>
> 文件在数据库中作为保存模型的一部分，因此在模型被保存之前，不能依赖磁盘上使用的实际文件名。

例如，您可以通过将文件的 [`name`](/zh-hans/4.2/ref/files/file/#django.core.files.File.name) 设置为相对于文件存储位置的路径（如果使用默认的 [`FileSystemStorage`](/zh-hans/4.2/ref/files/storage/#django.core.files.storage.FileSystemStorage)，则为 [`MEDIA_ROOT`](/zh-hans/4.2/ref/settings/#std-setting-MEDIA_ROOT)）来更改文件名：

```pycon
>>> import os
>>> from django.conf import settings
>>> initial_path = car.photo.path
>>> car.photo.name = "cars/chevy_ii.jpg"
>>> new_path = settings.MEDIA_ROOT + car.photo.name
>>> # Move the file on the filesystem
>>> os.rename(initial_path, new_path)
>>> car.save()
>>> car.photo.path
'/media/cars/chevy_ii.jpg'
>>> car.photo.path == new_path
True
```

将磁盘上的现有文件保存到 [`FileField`](/zh-hans/4.2/ref/models/fields/#django.db.models.FileField)：

```pycon
>>> from pathlib import Path
>>> from django.core.files import File
>>> path = Path("/some/external/specs.pdf")
>>> car = Car.objects.get(name="57 Chevy")
>>> with path.open(mode="rb") as f:
...     car.specs = File(f, name=path.name)
...     car.save()
...
```

> **Note**
>
> 虽然 [`ImageField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ImageField) 的非图像数据属性，如 `height`、`width` 和 `size` 可以在实例上使用，但底层图像数据不能在不重新打开图像的情况下使用。例如：
>
> ```pycon
> >>> from PIL import Image
> >>> car = Car.objects.get(name="57 Chevy")
> >>> car.photo.width
> 191
> >>> car.photo.height
> 287
> >>> image = Image.open(car.photo)
> # Raises ValueError: seek of closed file.
> >>> car.photo.open()
> <ImageFieldFile: cars/chevy.jpg>
> >>> image = Image.open(car.photo)
> >>> image
> <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=191x287 at 0x7F99A94E9048>
> ```

## `File` 对象

在内部，Django 在任何需要表示文件的时候使用 [`django.core.files.File`](/zh-hans/4.2/ref/files/file/#django.core.files.File) 。

大部分情况下你只需要使用 Django 提供的 `File` （即附加到上述模型的文件或已经上传的文件）。

如果需要自己构造一个 `File`，最简单的方法是使用 Python 内置的 `file` 对象创建一个：

```pycon
>>> from django.core.files import File

# Create a Python file object using open()
>>> f = open("/path/to/hello.world", "w")
>>> myfile = File(f)
```

现在你可以使用 [`File`](/zh-hans/4.2/ref/files/file/#django.core.files.File) 类的任何属性和方法。

请注意，以这种方式创建的文件不会自动关闭。可以使用以下方法自动关闭文件：

```pycon
>>> from django.core.files import File

# Create a Python file object using open() and the with statement
>>> with open("/path/to/hello.world", "w") as f:
...     myfile = File(f)
...     myfile.write("Hello World")
...
>>> myfile.closed
True
>>> f.closed
True
```

在循环遍历大量对象时访问文件字段时关闭文件尤其重要。如果在访问文件后不手动关闭它们，可能会出现耗尽文件描述符的风险。这可能会导致以下错误：

```pytb
OSError: [Errno 24] Too many open files
```

## 文件存储

在后台，Django将如何以及在哪里存储文件的决策委托给文件存储系统。这个对象实际上理解文件系统、打开和读取文件等。

Django 的默认文件存储是 `'`[`django.core.files.storage.FileSystemStorage`](/zh-hans/4.2/ref/files/storage/#django.core.files.storage.FileSystemStorage)`'`。如果您没有在 [`STORAGES`](/zh-hans/4.2/ref/settings/#std-setting-STORAGES) 设置的 `default` 键中明确提供一个存储系统，那么将使用这个存储系统。

参阅下面内置默认文件存储系统的细节，也可以查看 [如何编写一个自定义的文件存储类](/zh-hans/4.2/howto/custom-file-storage/) 来了解编写自己的文件存储系统的信息。

### 存储对象

虽然大多数情况下，您会希望使用一个 `File` 对象（它会委托给适当的文件存储），但您也可以直接使用文件存储系统。您可以创建某个自定义文件存储类的实例，或者更常见的做法是使用全局默认的存储系统：

```pycon
>>> from django.core.files.base import ContentFile
>>> from django.core.files.storage import default_storage

>>> path = default_storage.save("path/to/file", ContentFile(b"new content"))
>>> path
'path/to/file'

>>> default_storage.size(path)
11
>>> default_storage.open(path).read()
b'new content'

>>> default_storage.delete(path)
>>> default_storage.exists(path)
False
```

查看 [文件存储 API](/zh-hans/4.2/ref/files/storage/) 来了解文件存储API。

### 内置文件存储类

Django 附带一个 [`django.core.files.storage.FileSystemStorage`](/zh-hans/4.2/ref/files/storage/#django.core.files.storage.FileSystemStorage) 类，这个类实现基础的本地文件系统文件存储。

例如，下面的代码将存储上传文件到 `/media/photos` 而会忽略你在  [`MEDIA_ROOT`](/zh-hans/4.2/ref/settings/#std-setting-MEDIA_ROOT) 的设置：

```
from django.core.files.storage import FileSystemStorage
from django.db import models

fs = FileSystemStorage(location="/media/photos")

class Car(models.Model):
    ...
    photo = models.ImageField(storage=fs)
```

自定义存储系统（ [Custom storage systems](/zh-hans/4.2/howto/custom-file-storage/) ）的工作方式也一样：将它们作为 `storage` 参数传递给 [`FileField`](/zh-hans/4.2/ref/models/fields/#django.db.models.FileField) 。

### 使用callable

你可以使用callable作为 [`FileField`](/zh-hans/4.2/ref/models/fields/#django.db.models.FileField) 或 [`ImageField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ImageField) 的 [`storage`](/zh-hans/4.2/ref/models/fields/#django.db.models.FileField.storage) 参数。它允许你在运行时修改存储参数，不同环境选择不同存储，例如。

当模型类被加载时，callable将进行判断，并返回 [`Storage`](/zh-hans/4.2/ref/files/storage/#django.core.files.storage.Storage) 实例。

例如：

```
from django.conf import settings
from django.db import models
from .storages import MyLocalStorage, MyRemoteStorage

def select_storage():
    return MyLocalStorage() if settings.DEBUG else MyRemoteStorage()

class MyModel(models.Model):
    my_file = models.FileField(storage=select_storage)
```

要设置在 [`STORAGES`](/zh-hans/4.2/ref/settings/#std-setting-STORAGES) 设置中定义的存储系统，可以使用 [`storages`](/zh-hans/4.2/ref/files/storage/#django.core.files.storage.storages)：

```
from django.core.files.storage import storages

def select_storage():
    return storages["mystorage"]

class MyModel(models.Model):
    upload = models.FileField(storage=select_storage)
```

> **Changed in Django 4.2**
>
> 支持 `storages` 已添加。
