day23-基于ajax文件上传和上传图片之后预览
一、前言
之前我们是用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