上传的文件和上传处理程序
上传的文件
class UploadedFile
在文件上传过程中,实际的文件数据存储在 request.FILES 中。这个字典中的每一个条目都是一个 UploadedFile
对象(或一个子类)—— 一个所上传文件的包装器。你通常会使用这些方法之一来访问上传的内容:
UploadedFile.read
()
从文件中读取整个上传的数据。小心使用这个方法:如果上传的文件很大,如果你试图把它读到内存中,它可能会让你的系统不堪重负。你可能会想使用 chunks()
来代替;见下文。
UploadedFile.multiple_chunks
(chunk_size=None)
如果上传的文件足够大,需要分块读取,返回 True
。默认情况下是大于 2.5 兆字节的文件,但这是可以配置的,见下文。
UploadedFile.chunks
(chunk_size=None)
一个生成器,返回文件的块。如果 multiple_chunks()
是 True
,你应该在循环中使用这个方法而不是 read()
。
在实践中,通常最简单的做法是一直使用 chunks()
。循环使用 chunks()
而不是使用 read()
可以确保大文件不会过度占用系统的内存。
以下是 UploadedFile
的一些有用属性:
UploadedFile.name
上传的文件名称(如 my_file.txt
)。
UploadedFile.size
上传文件的大小,以字节为单位。
UploadedFile.content_type
与文件一起上传的内容类型头(例如 text/plain 或 application/pdf)。就像用户提供的任何数据一样,你不应该相信上传的文件实际上是这种类型。你仍然需要验证该文件是否包含内容类型头所声称的内容 —— “信任但验证”。
UploadedFile.content_type_extra
包含传递给 content-type
头的额外参数的字典。这通常是由服务提供的,比如 Google App Engine,它代表你拦截和处理文件上传。因此,您的处理程序可能不会收到上传的文件内容,而是收到一个 URL 或其他指向文件的指针(参见 RFC 2388)。
UploadedFile.charset
对于 text/* 内容类型,浏览器提供的字符集(即 utf8
)。同样,“信任但验证” 是这里的最佳政策。
注解
像普通的 Python 文件一样,你可以通过迭代上传的文件来逐行读取文件:
for line in uploadedfile:
do_something_with(line)
使用 通用换行符 来分割行。以下是公认的行结束方式:Unix 的行末约定 '\n'
,Windows 的约定 '\r\n'
,以及旧的 Macintosh 约定 '\r'
。
UploadedFile
的子类包括:
class TemporaryUploadedFile
一个文件上传到一个临时位置(即传输到磁盘)。这个类被 TemporaryFileUploadHandler 使用。除了 UploadedFile 的方法外,它还有一个额外的方法:
TemporaryUploadedFile.temporary_file_path
()
返回临时上传文件的完整路径。
class InMemoryUploadedFile
一个上传到内存中的文件(即传输到内存)。这个类被 MemoryFileUploadHandler 使用。
内置上传处理程序
MemoryFileUploadHandler 和 TemporaryFileUploadHandler 共同提供了 Django 默认的文件上传行为,即向内存中读取小文件,向磁盘中读取大文件。它们位于 django.core.files.uploadhandler
中。
class MemoryFileUploadHandler
文件上传处理程序,将上传的文件以流式传输到内存中(用于小文件)。
class TemporaryFileUploadHandler
使用 TemporaryUploadedFile
将数据流式传输到临时文件的上传处理程序。
编写自定义上传处理程序
class FileUploadHandler
所有的文件上传处理程序应该是 django.core.files.uploadhandler.FileUploadHandler
的子类。你可以在任何地方定义上传处理程序。
必要方法
自定义文件上传处理程序 必须 定义以下方法:
FileUploadHandler.receive_data_chunk
(raw_data, start)
接收文件上传的 “块” 数据。
raw_data
是一个包含上传数据的字节字符串。
start
是文件中 raw_data
块开始的位置。
你返回的数据将被输入到后续的上传处理程序的 receive_data_chunk
方法中。通过这种方式,一个处理程序可以成为其他处理程序的 “过滤器”。
从 receive_data_chunk
中返回 None
,以短路剩余的上传处理程序。如果你自己存储上传的数据,并且不希望后续的处理程序存储数据的副本,这很有用。
如果引发一个 StopUpload
或 SkipFile
异常,上传将被中止或文件将被完全跳过。
FileUploadHandler.file_complete
(file_size)
当文件上传完毕时调用。
处理程序应返回一个 UploadedFile
对象,该对象将存储在 request.FILES
中。处理程序也可以返回 None
以表明 UploadedFile
对象应来自后续的上传处理程序。
可选方法
自定义上传处理程序也可以定义以下任何一个可选方法或属性:
FileUploadHandler.chunk_size
Django 应该存储到内存中并反馈给处理程序的 “块” 的大小,以字节为单位。也就是说,这个属性控制了输入到 FileUploadHandler.receive_data_chunk
的数据块的大小。
为了获得最大的性能,分块大小应该被 4
整除,并且大小不能超过 2GB(231 字节)。当有多个处理程序提供的多个分块大小时,Django 将使用任何处理程序定义的最小分块大小。
默认为 64*210 字节,即 64KB。
FileUploadHandler.new_file
(field_name, file_name, content_type, content_length, charset, content_type_extra)
回调信号,表示一个新的文件上传开始。在任何数据被送入任何上传处理程序之前,这个回调被调用。
field_name
是文件 <input>
字段的字符串名称。
file_name
是浏览器提供的文件名。
content_type
是浏览器提供的 MIME 类型 —— 例如 'image/jpeg'
。
content_length
是浏览器给出的图像长度。有时不会提供,而是 None
。
charset
是浏览器提供的字符集(即 utf8
)。与 content_length
一样,有时不会提供。
content_type_extra
是关于文件的 content-type
头的额外信息。参见 UploadedFile.content_type_extra。
这个方法可能会引发一个 StopFutureHandlers
异常,以防止后续处理程序处理这个文件。
FileUploadHandler.upload_complete
()
回调信号,表示整个上传(所有文件)已经完成。
FileUploadHandler.upload_interrupted
()
New in Django 3.2.
回调信号,表明上传被中断,例如,当用户在文件上传过程中关闭他们的浏览器。
FileUploadHandler.handle_raw_input
(input_data, META, content_length, boundary, encoding)
允许处理程序完全覆盖原始 HTTP 输入的解析。
input_data
是一个支持 read()
-ing 的类文件对象。
META
与 request.META
是同一个对象。
content_length
是 input_data
中数据的长度。不要从 input_data
中读取超过 content_length
的字节。
boundary
是本次请求的 MIME 边界。
encoding
是请求的编码。
如果想继续上传处理,则返回 None
,如果想直接返回适合请求的新数据结构,则返回 (POST,FILES)
的元组。