当Django处理上传一个文件的时候,文件数据被放在request.FILES中。视图将在request.FILES中接受文件数据 ,request.FILES是一个字典,它对每个FileField(或者是ImageField,或者是其他的FileField的子类)都包含一个key.所以 从表单来的数据可以通过request.FILES.get("key")或者request.FILES['key']键来访问。

    

    配置上传的文件路径

    在settings.py中配置MEDIA_URL和MEDIA_ROOT

    MEDIA_URL = '/upload/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'upload')


1、表单模板 uploadfile.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
<form method="post" action="" enctype="multipart/form-data" >
    {% csrf_token %}
    <input type="file" name="uploadfile" /><br /><br /><br />
    <input type="submit" value="提交"/>
</form>
<br />
<img src={{ file_url }} width="100px" height="100px" />
<br />
{{ res }}
</body>
</html>


    特别注意的是,只有当request方法是POST,且发送request的<form>有属性enctype="multipart/form-data"时,request.FILES中才包含文件数据,否则request.FILES为空。


2、视图函数

import os
import uuid
import json
import datetime as dt
def upload_files(request):
    if request.method == "POST":            #判断方法是否为post
        f = request.FILES.get("uploadfile")        #从request.FILES获取名为uploadfile的数据
        if f:
            allow_suffix = ['jpg', 'png', 'jpeg', 'gif', 'bmp']  #定义一个允许上传的文件格式列表
            file_suffix = f.name.split(".")[-1]            #获取上传数据文件的后缀
            if file_suffix not in allow_suffix:            #判断是否匹配上传格式列表
                #return HttpResponse(json.dumps({"error": 1, "message": "Format ERROR!!"}),content_type="application/json")
                return render(request, 'uploadfile.html', {'res': '文件格式错误!', 'uploadfile': f.name})
            uploaddir = os.path.join(settings.MEDIA_ROOT, 'p_w_picpaths/')
            today = dt.datetime.today()
            dir_name = uploaddir + '/%d/%d/' % (today.year, today.month)
            filename = os.path.join(uploaddir, dir_name, f.name)        #文件名,已绝对路径保存
            file_url = os.path.join(settings.MEDIA_URL,'p_w_picpaths/%d/%d/',f.name) % (today.year, today.month)    #文件名相对路径
            if not os.path.exists(dir_name):  # 如果目录不存在创建目录
                os.makedirs(dir_name)

            fobj = open(filename, 'wb')    #打开文件(创建保存文件)
            for chrunk in f.chunks():        #循环写入数据
                fobj.write(chrunk)
            fobj.close()        #关闭文件
            return render(request, 'uploadfile.html', {'res': '文件上传成功!', 'file_url':file_url})
            #return HttpResponse(json.dumps({"error": 0, "message": "Upload Success!!"}), content_type="application/json")
        else:
            return render(request, 'uploadfile.html', {'res': '请先选择需要上传的文件!'})
            #return HttpResponse(json.dumps({"error": 1, "message": "Upload Failed"}), content_type="application/json")

    else:
        return render(request,'uploadfile.html')


    难题是怎样处理从request.FILES中获得的真实的文件。这个字典的每一个条目都是一个UploadFile对象(一个上传之后的文件的简单的包装。)

    通常会使用下面的几个UploadFile对象方法来访问被上传的内容:

    1、UploadFile.read():

    从文件中读取全部上传数据。当上传文件过大时,可能会耗尽内存,慎用。

    2、UploadFile.multiple_chunks():

    如上传文件足够大,要分成多个部分读入时,返回True.默认情况,当上传文件大于2.5M时,返回True。但这一个值可以配置。

    3、UploadFile.chunks():

返回一个上传文件的分块生成器。如multiple_chunks()返回True,必须在循环中使用chrunks()来代替read()。一般情况下直接使用chunks()就行。

    4、UploadFile.name():上传文件的文件名

    5、UplaodFile.size():上传文件的文件大小(字节)


3、配置urls路由

    url(r'uploadfile/$',upload_files,name="uploadffile"),