一、前言
之前我们是用forms的方式去上传文件,后台去读取,然后去写入到后台去,具体博客:day18-Django获取1个或多个数据以及文件上传 ,我们今天使用的是,ajax方式去操作文件上传的动作,这边有三种方式,
- 原生ajax上传文件
- jquery的ajax的上传文件
- iframe方式(伪ajax方式)上传文件
这个上传文件我们说完了,下面还有就是上传图片之后的预览,这个我们也要学会的,这个我们下面会一步一步的详细的介绍的,下面进入正题吧。
二、操作前提
2.1、路由url的设置
说明:我们首先设置一下路由
from django.urls import path
from app01.views import test
urlpatterns = [
path('upload/',test.upload), #上传文件页面
path('upload_file/',test.upload_file), #上传文件功能
]
2.2、upload函数
说明:通过upload函数显示上传页面
def upload(request):
return render(request,'upload.html')
2.3、upload_file函数
说明:这边主要处理上传过来的文件,写到服务器上
def upload_file(request):
username = request.POST.get('username')
fafafa = request.FILES.get('fafafa')
print(username,fafafa) #输出 root settings.xml
with open(fafafa.name,'wb') as f:
for item in fafafa.chunks(): #把文件写入到服务器端
f.write(item)
ret = {'code':True,'data':request.POST.get('username')}
import json
return HttpResponse(json.dumps(ret))
2.4、upload.html的模板
说明:这边我只写html和css部分,js上传功能,我们下面详细的讲解,这边静态的东西如下:


<head> <meta charset="UTF-8"> <title>Title</title> <style> .upload{ display: inline-block; padding: 10px; background-color: brown; top: 0; bottom: 0; right: 0; left: 0; z-index: 99; } .file{ width: 100px;height: 50px;opacity: 0; position: absolute; top: 0; bottom: 0; right: 0; left: 0; z-index: 100; } </style> </head> <body> <!--原生ajax和jquery ajax上传文件定义的html--> <div style="position: relative;width: 100px;height: 50px;"> <!--因为这个改不了,所以这个上传的标签只能自定义组件,就是在外面嵌套div--> <input class="file" type="file" id="fafafa" name="afafaf"> <a class="upload">上传</a> </div> <!--原生ajax的触发按钮--> <input type="button" value="提交XHR" onclick="xhrSubmit();"/> <!--jquery的发送方式触发按钮--> <input type="button" value="提交Jquery" onclick="jqSubmit();"/> <!--分隔符--> <hr/> <!--伪类ajax上传文件定义的html--> <form action="/upload_file/" method="post" enctype="multipart/form-data" target="ifm1"> <iframe id="ifm1" name="ifm1"></iframe> <!--正常情况下,iframe在前端是不显示的,但是我们这边为了方便调试,所以暂时打开--> <input type="file" name="fafafa"/> <!--iframe方式上传文件--> <input type="submit" onclick="iframeSubmit();" value="Form提交"/> </form> <!--图片存放的地方--> <div id="preview"></div> </body> </html>
如图:
三、文件上传
3.1、原生ajax文件上传
说明:原生ajax需要在FormData的支持下,才能发送文件的对象到后台
<script src="/static/jquery-1.12.4.js"></script>
<script>
function xhrSubmit(){
//$('#fafafa')[0] //[0]表示是dom对象
var file_obj = document.getElementById("fafafa").files[0]; //files表示你要上传的文件,这边只上传一个文件,所以用[0],指的就是上传的文件对象
var fd = new FormData(); // formdata相当于form表单
fd.append('username','root'); // 加普通字符串四可以的,加obj对象也是可以的
fd.append('fafafa',file_obj);
var xhr = new XMLHttpRequest();
xhr.open('post','/upload_file/',true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
//接收完毕
var obj = JSON.parse(xhr.responseText);
console.log(obj);
}
};
xhr.send(fd); //这边发送的话,就直接发送fd对象了
}
</script>
3.2、jquery的方式发送
说明:利用jquery自带的ajax的功能发送文件、图片或者等其他静态文件,这种方式也是要依赖 formdata的
<script>
function jqSubmit(){
var file_obj = document.getElementById('fafafa').files[0];
var fd = new FormData();
//发普通文本的话,我们是这样发的,但是如果发文件或者图片的话,你要告诉jquery,因为jquery内部需要处理
fd.append('username','root');
fd.append('fafafa',file_obj);
$.ajax({
url:'/upload_file/',
type:'post',
data:fd, //直接发送formdata对象给后端
processData:false,//tell jQuery not to process the data
contentType:false,// tell jQuery not to set contentType
success:function(args,statusText,xhr){
console.log(args);
console.log(statusText);
console.log(xhr); //XMLHttprequest对象
}
})
}
</script>
</body>
前端返回的信息如图,这个我们都可以通过xmlhttprequest对象可以获取到:
3.3、iframe的方式上传(伪ajax上传)
说明:我们现在用第三种方式上传,其实大部分都是以这种方式上传,包括抽屉网,这个我就不给大家介绍了,可以去看看。
<script src="/static/jquery-1.12.4.js"></script>
<script>
function iframeSubmit(){ //form本身就已经提交了
$('#ifm1').bind('load',function(){ //提交之后,会自动执行iframe会自动执行onload事件
var text = $('#ifm1').contents().find('body').text(); //获取iframe body中的内容
var text_obj = JSON.parse(text);
console.log(text_obj);
})
}
</script>
四、上传图片之后预览
4.1、upload_file函数修改
说明:我们这边在 后台的 static 下建一个imgs 文件夹,我们所有的图片都放在这个下面,所以我们返回一个图片路径给前端,代码如下:
def upload_file(request):
username = request.POST.get('username')
fafafa = request.FILES.get('fafafa')
import os
img_path = os.path.join('static/imgs/',fafafa.name) #设置img的路径
with open(img_path,'wb') as f: #直接写入指定 static/imgs文件下
for item in fafafa.chunks():
f.write(item)
ret = {'code':True,'data':img_path} #data这边返回是图片的路径
import json
return HttpResponse(json.dumps(ret))
4.2、上传预览
说明:上传图片之后,我们预览图片,js代码如下:
<script src="/static/jquery-1.12.4.js"></script>
<script>
function iframeSubmit(){
$('#ifm1').bind('load',function(){
var text = $('#ifm1').contents().find('body').text();
var text_obj = JSON.parse(text);
//存在就清空一下
$('#preview').empty();
var img_tag = document.createElement('img');
img_tag.src = '/' + text_obj.data; //这边由于后台的path是static/imgs,所以这边要在前面加一个 '/'
$('#preview').append(img_tag); //在div中加一个img标签
})
}
</script>
显示效果图:
4.3、自动上传预览
说明:就是说我们不需要点击From提交按钮,预览图片,我只要上传图片了,就自动给我展示,这边要给上传的 按钮帮你一个 onchange事件,就是说,只要上传的图片已经改变,就自动提交
1、前端 iframe 的代码改进
<form id="fm1" action="/upload_file/" method="post" enctype="multipart/form-data" target="ifm1">
<!--iframe默认情况下不显示,不让用户看到,但是我们调试的时候可以打开-->
<iframe id="ifm1" name="ifm1" style="display: none"></iframe>
<!--绑定onchange事件,只要一改变,让整个表单提交-->
<input type="file" name="fafafa" onchange="changeUpload();"/>
<!--iframe方式上传文件-->
<!--<input type="submit" onclick="iframeSubmit();" value="Form提交"/>-->
</form>
<!--图片存放的地方-->
<div id="preview"></div>
2、js的代码
说明:我们先绑定一个事件,首先先要执行的iframe的onload的事件,然后再直接提交 form表单就可以了。
<script src="/static/jquery-1.12.4.js"></script>
<script>
function changeUpload(){
// 先绑定一个事件,然后我们再提交,上面的submit按钮直接注释掉
$('#ifm1').bind('load',function(){
var text = $('#ifm1').contents().find('body').text();
var text_obj = JSON.parse(text);
//存在就清空一下
$('#preview').empty();
var img_tag = document.createElement('img');
img_tag.src = '/' + text_obj.data;
$('#preview').append(img_tag);
});
$('#fm1').submit(); //这步操作放在 $('#ifm1').bind('load',function(){}上面也是可以的,可能这个是一个自执行函数,肯定是要先提交,然后才会获取图片
}
</script>
效果图:
五、总结
1、原生ajax(xhr)和jquery ajax($.ajax) 都需要依赖 FormData 对象,但是这个东西不是所有的浏览器都支持的,IE的低版本不支持。
2、iframe这个东西在所有浏览器上都使用,其他两种方式只有非IE浏览器使用。
3、三个的优先级顺序: iframe -> jquery ajax -> 原生 ajax