• Django:学习笔记(8)——文件上传


    Django:学习笔记(8)——文件上传

    文件上传前端处理

      本模块使用到的前端Ajax库为Axio,其地址为GitHub官网

    关于文件上传

      上传文件就是把客户端的文件发送给服务器端。

      在常见情况(不包含文件上传)下,我们POST请求Content-Type是application/x-www-form-urlencoded,这意味着消息内容会经过URL编码,就像在GET请求时URL里的QueryString那样。txt1=hello&txt2=world。为了支持表单上传,我们第一个要设置的请求的Content-Type,即为multipart/form-data,以支持客户端向服务器发送二进制数据。

      一个常见的请求上传格式大概是这样的:

      

    基于表单进行上传

      我们首先构建一个简易的文件上传表单,这里面有几个需要注意的地方:

    • 在form中,我们添加了enctype="multipart/form-data" 这条属性,enctype属性规定了在发送到服务器之前应该如何对表单数据进行编码
    • action="upload"> 指明了服务器接受文件的地址。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form name="uploadForm" method="POST" enctype="multipart/form-data" action="upload">
            <table>
                <tr>
                    <td>UserName</td>
                    <td><input type="text" name="username"></td>
                </tr>
                <tr>
                    <td>upload1</td>
                    <td><input type="file" name="file"></td>
                </tr>
                <tr><td><input type="submit" name="submit" value="上传"></td></tr>
            </table>
        </form>
    </body>
    </html>
    

      然后,再点击上传按钮后,服务器将会接收到上传请求。 

    补充:

      在HTML5中,通过在input元素中引入多个multiple属性,使得多个文件的上传变得更加简单,下面均可使一个上传框支持多个文件上传。

    <input type="file" name="fieldName" multiple/>
    <input type="file" name="fieldName" multiple="multiple"/>
    <input type="file" name="fieldName" multiple=""/>

    基于FormData进行上传

      FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。如果表单enctype属性设为multipart/form-data ,则会使用表单的submit()方法来发送数据,从而,发送数据与传统表单具有同样形式。

      简单来说就是,我们完全用JavaScript代码来拼写表单数据,如下:

    var formData = new FormData();
    
    //普通字段
    formData.append("username", "Groucho");
    formData.append("accountnum", 123456); //数字123456会被立即转换成字符串 "123456"
    
    // 文件:基于<input type=‘file’/>
    formData.append("userfile", fileInputElement.files[0]);
    
    // 文件:Blob 对象
    var content = '<a id="a"><b id="b">hey!</b></a>'; // 新文件的正文...
    var blob = new Blob([content], { type: "text/xml"});
    formData.append("webmasterfile", blob);
    

      接着,我们就可以使用axios,来上传数据,此处需要注意的是,我们需要进行请求头的设置:'Content-Type': 'multipart-/form-data'

    //构造表头
    let config = {
                headers: {
                    'Content-Type': 'multipart-/form-data'
                }
            }
    
    axios.post("//127.0.0.1:8000/web/cam", formData, config)
    	.then((response) => {…}))
    	.catch((error) =>{…});
    

      到这里,前端的处理就完成了。  

     

    Django处理文件上传请求

    简单模式

      所谓简单模式,就是我们不使用Django的高级特性,单单从文件的接收、保存与读取考虑。首先,我们知道文件数据会保存在request.FILES中。

      

      我们通过,request.FILES['文件名'],来获取指定的文件,然后将其保存。

    def SaveImage(image):
        imgname = settings.MEDIA_ROOT+"/"+image.name
        with open(imgname,'wb') as f:
            for fimg in image.chunks():
                f.write(fimg)
        return imgname
    

      函数最后,返回imgname表示图片的地址,我们可以使用读取命令,来读取图片数据。

    基于表单模型

      首先,我们需要创建一个表单模型,其中file会映射请求中名为file的文件数据。

    # forms.py
    from django import forms
    
    class UploadFileForm(forms.Form):
        title = forms.CharField(max_length=50)
        file = forms.FileField()
    

      然后,编写视图,其中一定要注意,需要将两个参数传递给表单模型UploadFileForm(request.POST, request.FILES) ,之后就可以进行表单验证了。最后交由处理函数来处理上传的文件。

    # views.py
    
    from django.http import HttpResponseRedirect
    from django.shortcuts import render
    from .forms import UploadFileForm
    
    # 另外写一个处理上传过来的文件的方法,并在这里导入
    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只有在请求方法为POST,并且提交请求的<form>具有enctype="multipart/form-data"属性时才有效。 否则,request.FILES将为空。

      我们可以调用调用form.save(),这样文件对象会保存在相应的FileField的upload_to参数指定的地方。

      还有一个需要注意的地方,我们可以直接把文件对象直接从request.FILES赋值给模型:

    from .models import ModelWithFileField
    ... 
    instance = ModelWithFileField(file_field=request.FILES['file'])
    

      

  • 相关阅读:
    快速幂算法
    素数筛
    数论知识点总结
    ABOUT MY NAME
    CF1043F Make It One
    树形DP
    魔兽世界联盟8.1主线任务
    模板std::mutex用法:
    【转】正确的提问方式
    第一个Python游戏窗口
  • 原文地址:https://www.cnblogs.com/MrSaver/p/10546833.html
Copyright © 2020-2023  润新知