Django文件上传实战:Form、Ajax与ContentType详解
本文深入解析Django中文件上传的多种实现方式,涵盖原生Form表单与Ajax异步提交。重点讲解application/x-www-form-urlencoded、multipart/form-data及application/json三种Content-Type的区别与应用场景,并提供基于jQuery的Ajax上传代码示例及后端视图处理逻辑,帮助开发者掌握Django文件处理的核心技术。
近期状态有所波动,如今已调整完毕,让我们继续追寻技术的梦想。
本文将补充介绍几种常见的文件上传实现方案。
首先,我们需要补充一个关键的前端知识点。
一、请求头ContentType详解:
ContentType用于指定请求体的编码类型,常见的类型主要有三种。
1、application/x-www-form-urlencoded
这是最常见的POST数据提交方式。当浏览器的原生<form>表单未设置enctype属性时,默认即以此方式提交数据。其请求格式大致如下(省略无关请求头):
POST http://www.example.com HTTP/1.1 Content-Type: application/x-www-form-urlencoded;charset=utf-8 user=duoduo&age=22
2、multipart/form-data
这是另一种常见的POST数据提交方式。在使用表单上传文件时,必须将<form>表单的enctype属性设置为multipart/form-data。
POST http://www.example.com HTTP/1.1 Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA ------WebKitFormBoundaryrGKCBY7qhFd3TrwA Content-Disposition: form-data; name="user" duoduo ------WebKitFormBoundaryrGKCBY7qhFd3TrwA Content-Disposition: form-data; name="file"; filename="chrome.png" Content-Type: image/png PNG ... content of chrome.png ... ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
该示例相对复杂。首先生成一个boundary用于分割不同字段,为避免与正文内容重复,boundary通常较长且复杂。Content-Type中指明了数据以multipart/form-data编码,并指定了本次请求的boundary内容。消息主体按字段数量分为多个结构相似的部分,每部分以--boundary开始,紧接着是内容描述信息,随后是回车符,最后是字段具体内容(文本或二进制)。若传输文件,还需包含文件名和文件类型信息。消息主体最后以--boundary--标示结束。关于multipart/form-data的详细定义,请参考rfc1867标准。
这种方式通常用于上传文件,各大服务端语言均对其有良好支持。
上述两种POST数据方式均为浏览器原生支持,且现阶段标准中原生<form>表单仅支持这两种方式(通过<form>元素的enctype属性指定,默认为application/x-www-form-urlencoded。实际上enctype还支持text/plain,但使用频率极低)。
随着越来越多的Web站点,尤其是WebApp,全面采用Ajax进行数据交互,我们可以定义新的数据提交方式,从而为开发带来更多便利。
3、application/json
application/json作为响应头大家可能并不陌生。实际上,现在越来越多的人将其作为请求头,用于告知服务端消息主体是序列化后的JSON字符串。得益于JSON规范的流行,除低版本IE外,各大浏览器均原生支持JSON.stringify,服务端语言也提供了处理JSON的函数,使用JSON几乎不会遇到障碍。
JSON格式支持比键值对更为复杂的数据结构,这一点颇具价值。记得几年前开发项目时,需要提交的数据层次非常深,我便将数据JSON序列化后提交。当时我将JSON字符串作为val,仍置于键值对中,以x-www-form-urlencoded方式提交。
二、基于Form表单的文件上传
模块部分
<form action="" method="post" enctype="multipart/form-data"> 用户名 <input type="text" name="user"> 头像 <input type="file" name="avatar"> <input type="submit"> </form>
视图部分
def index(request): print(request.body) # 原始的请求体数据 print(request.GET) # GET请求数据 print(request.POST) # POST请求数据 print(request.FILES) # 上传的文件数据 return render(request,"index.html")
三、基于Ajax的文件上传
模块
<form>
用户名 <input type="text" id="user">
头像 <input type="file" id="avatar">
<input type="button" id="ajax-submit" value="ajax-submit">
</form>
<script>
$("#ajax-submit").click(function(){
var formdata=new FormData();
formdata.append("user",$("#user").val());
formdata.append("avatar_img",$("#avatar")[0].files[0]);
$.ajax({
url:"",
type:"post",
data:formdata,
processData: false , // 不处理数据
contentType: false, // 不设置内容类型
success:function(data){
console.log(data)
}
})
})
</script>
视图
def index(request):
if request.is_ajax():
print(request.body) # 原始的请求体数据
print(request.GET) # GET请求数据
print(request.POST) # POST请求数据
print(request.FILES) # 上传的文件数据
return HttpResponse("ok")
return render(request,"index.html")
检查浏览器的请求头:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryaWl9k5ZMiTAzx3FT
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









