一、请求头之contentType
1、ContentType指的是请求体的编码类型,常见的类型共有3种:application/x-www-form-urlencoded、 multipart/form-data、application/json
2、 application/x-www-form-urlencoded
这应该是最常见的 POST 提交数据的方式了。浏览器的原生表单,
如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
#可以用request.POST与request.GET获取到值
3、multipart/form-data
这又是一个常见的 POST 数据提交的方式。######我们使用表单上传文件时,必须让表单的 enctype 等于 multipart/form-data。######
#可以用request.FILES获取到值
4、application/json
(1)application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。
由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
(2)JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。
不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。
#Django内置的没有json的解析器,需要我们在request.body中按照相应的规则去处理~
1、路由
re_path('^put_file/$',views.put_file),
2、视图函数
def put_file(request):
if request.method == 'GET':
return render(request,'put_file.html')
if request.method == 'POST':
print(request.POST) #<QueryDict: {'user': ['123']}>
# 用request.FILES获取
print(request.FILES) # #<MultiValueDict: {'avatar': [<InMemoryUploadedFile: 1.jpg (image/jpeg)>]}>
#上传文件——默认传到程序的根目录
#获取文件对象
#这个file_obj是一个文件句柄类型的数据
file_obj = request.FILES.get('avatar')
#注意这里:file_obj.name,以二进制方式写入
#拼接路径 这里存放上传的文件的位置可以用绝对路径~这里我在静态文件夹中新建了一个upload文件夹存放上传的文件
file_path = os.path.join(settings.BASE_DIR,'staticfiles','upload',file_obj.name)
#按照绝对路径写入文件
with open(file_path,'wb')as f:
#django内置的方法chunks()方法
#chunks()默认一次返回大小为经测试为65536B,也就是64KB,最大为2.5M,是一个生成器
for chunk in file_obj.chunks():
f.write(chunk)
return HttpResponse('OK!')
3、模板文件——put_file.html
<form action='' method='post' enctype="multipart/form-data">
{% csrf_token %}
用户名: <input type="text" name="user"> </br></br>
文 件: <input type="file" name="avatar"> </br></br>
<input type="submit">
</form>
三、基于Ajax的文件上传
1、路由
re_path('index',views.ajax_upload,name='ajax_upload'),
2、视图函数
def ajax_upload(request):
if request.method == 'POST':
print(request.POST)
print(request.FILES)
# 注意 这里用的是formdata的键~
print(request.FILES.get('file_obj'))
# 这个file_obj是一个文件句柄类型的数据
file_obj = request.FILES.get('file_obj')
print(file_obj.name) # default.jpg 本地文件的名称要跟他一致
# 拼接路径
file_path = os.path.join(settings.BASE_DIR, 'staticfiles', 'upload', file_obj.name)
# 读文件
with open(file_path, 'wb')as f:
# django内置的方法chunks()方法 每次上传的都是一个固定大小的数据
for chunk in file_obj.chunks():
f.write(chunk)
return HttpResponse('OK')
else:
return render(request,'ajax_upload.html')
3、模板文件——ajax_upload.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajax上传</title>
</head>
<body>
<div>
{# csrf_token认证需要的标签 #}
{% csrf_token %}
用户名:<input id="user" type="text" name="username" placeholder="用户名">
密码:<input id="pwd" type="password" name="password" placeholder="密码">
头像:<input id="avatar" type="file" name="avatar">
<input type="button" value="上传文件" id="btn">
</div>
</body>
<script src="{% static 'jquery-3.4.1.js' %}"></script>
{# 注意引入jquery.cookie.js 进行csrfmiddlewaretoken认证 #}
<script src="{% static 'jquery-cookie/jquery.cookie.js' %}"></script>
<script>
$('#btn').click(function () {
var username = $('#user').val();
var password = $('#pwd').val();
//取到的jquery对象转换成dom对象~然后调用dom对象的files方法获取所有的文件
//这里是单个文件的上传~~取第一个就好了~~~
var file_obj = $('#avatar')[0].files[0];
{# 声明一个formdata对象 并将需要传递的数据append到里面去 #}
{# 注意:是在ajax操作之前做的! #}
var formdata = new FormData();
formdata.append('uname',username);
formdata.append('pwd',password);
formdata.append('file_obj',file_obj);
$.ajax({
url:{% url 'ajax_upload'%},
type:'post',
data:formdata,
// 从Cookie取csrftoken,并设置到请求头中,进行csrfmiddlewaretoken认证
headers: {"X-CSRFToken": $.cookie('csrftoken')},
{# 用formdata进行ajax文件上传必须加这两个参数 #}
processData: false , // 不处理数据
contentType: false, // 不设置内容类型
success:function (data) {
console.log(data);
}
})
})
</script>
</html>