zoukankan      html  css  js  c++  java
  • 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'])
    

      

  • 相关阅读:
    298. Binary Tree Longest Consecutive Sequence
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    163. Missing Ranges
    336. Palindrome Pairs
    727. Minimum Window Subsequence
    211. Add and Search Word
    年底购物狂欢,移动支付安全不容忽视
    成为程序员前需要做的10件事
    全球首推iOS应用防破解技术!
  • 原文地址:https://www.cnblogs.com/MrSaver/p/10546833.html
Copyright © 2011-2022 走看看