3期 61-1 django文件上传
一、【 Form表单 】文件上传
提交数据后,页面自动刷新。
1、基本使用
原理 :使用type为“file”的input框。
- form表单必须加上属性 enctype="multipart/form-data"
- 使用request.Files接收
- 文件对象有name、size、chunks
def upload(request): if request.method == 'GET': return render(request, 'upload.html') else: print(request.POST) # <QueryDict: {'user': ['张小静'], '提交': ['提交'], 'csrfmiddlewaretoken': ['WLovl00fInI6casPsGh0HrZwRcWtjT3sPlxtCSS9yQXrGF5YLNToNVLaKSfRQwAB']}> print(request.FILES) # <MultiValueDict: {'img': [<InMemoryUploadedFile: 1.jpg (image/jpeg)>]}> user = request.POST.get('user') img = request.FILES.get('img') # 获取到的是一个文件对象 print(img.name) # 101101.jpg 文件名称 print(img.size) # 84067 文件大小 print(img.chunks) # <bound method InMemoryUploadedFile.chunks of <InMemoryUploadedFile: 101101.jpg (image/jpeg)>> f = open(img.name, 'wb') # 服务器端创建一个文件f for line in img.chunks(): f.write(line) f.close() return HttpResponse('上传成功!')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--enctype="multipart/form-data" 必须写--> <form action="/upload.html", method="POST" enctype="multipart/form-data"> 会员姓名:<input type="text" name="user"><br> 会员头像:<input type="file" name="img"><br> <input type="submit" name="提交"> {% csrf_token %} </form> </body> </html>
2、基于Form组件
原理:可用django的Form组件自动生成input框及处理提交的数据。
from django import forms from django.forms import fields class UploadForm(forms.Form): user = fields.CharField() img = fields.FileField() def upload_by_form(request): if request.method == 'GET': return render(request, 'upload3.html') else: uform_obj = UploadForm(request.POST, request.FILES) # 注意:要写上request.FILES if uform_obj.is_valid(): user = uform_obj.cleaned_data['user'] img = uform_obj.cleaned_data['img'] f = open(img.name, 'wb') for line in img.chunks(): f.write(line) f.close() return HttpResponse('上传成功3') else: return render(request, 'upload3.html')
二、【 Iframe标签+Form表单 】文件上传
提交数据后,页面不自动刷新。兼容性强。
原理:form表单提交数据,iframe作为通道。
def upload1(request): if request.method == 'GET': return render(request, 'upload1.html') else: user = request.POST.get('user') img = request.FILES.get('img') # 获取到的是一个文件对象 f = open(img.name, 'wb') # 服务器端创建一个文件f for line in img.chunks(): f.write(line) f.close() return HttpResponse('上传成功!')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--iframe作为通道+form提交数据 配合使用,不刷新页面的情况下上传文件--> <!--要点:form表单的target属性值要等于iframe标签的name值--> <iframe style="display:none" name="ifra"></iframe> <form action="/upload.html", method="POST" enctype="multipart/form-data" target="ifra"> 会员姓名:<input type="text" name="user"><br> 会员头像:<input type="file" name="img"><br> <input type="submit" name="提交"> {% csrf_token %} </form> </body> </html>
实例:上传图片后,立即预览
def upload_show(request): if request.method == 'GET': return render(request, 'upload_show.html') else: user = request.POST.get('user') file_obj = request.FILES.get('img') # 获取到的是一个文件对象 import uuid nid = str(uuid.uuid4()) # 制作要保存文件的路径 import os file_path = os.path.join("static\images", nid+"-"+file_obj.name) # 将文件保存在指定路径 f = open(file_path, 'wb') for line in file_obj.chunks(): f.write(line) f.close() dic = {"status": True, "data": file_path} import json ret = json.dumps(dic) return HttpResponse(ret)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="preview"></div> <!--iframe作为通道+form提交数据 配合使用,不刷新页面的情况下上传文件--> <iframe id="iframe" style="display:none" name="ifra"></iframe> <form id="fm" action="/upload_show.html", method="POST" enctype="multipart/form-data" target="ifra"> 会员姓名:<input type="text" name="user"><br> 会员头像:<input type="file" name="img"><br> <button onclick="AjaxSubmit5()">提交</button> {% csrf_token %} </form> <script src="/static/jquery-3.2.1.js"></script> <script> function AjaxSubmit5(){ // 需要回调函数接收服务器发回的数据时,通过加onload事件实现 //点击按钮后,先给iframe绑定onload事件。因为iframe接收到服务器返回的信息时,有重新加载的过程 document.getElementById("iframe").onload = reLoadIframe; //reloadIFrame就相当于回调函数了 //form表达提交数据 document.getElementById("fm").submit() } function reLoadIframe(){ var content = this.contentWindow.document.body.innerHTML; //接收服务器发回的信息 console.log(content); var obj = JSON.parse(content); if (obj.status){ // 新建img元素 var tag = document.createElement('img'); tag.src = obj.data; tag.width = 200; tag.height = 200; $('#preview').empty().append(tag); } } </script> </body> </html>
三、【 Ajax 】文件上传
提交数据后,页面自动刷新。
原理:先将数据封装在FormData对象中,然后基于XMLHttpResponse对象发送给服务器。
1、原生XMLHttpResponse方式
def upload5(request): if request.method == 'GET': return render(request, 'upload5.html') else: print(request.POST) user = request.POST.get('user') img = request.FILES.get('img') # 获取到的是一个文件对象 f = open(img.name, 'wb') # 服务器端创建一个文件f for line in img.chunks(): f.write(line) f.close() return HttpResponse('上传成功!')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 会员姓名:<input id="user" type="text"><br> 会员头像:<input id="img" type="file"><br> <button id="btn" onclick="func1()">提交</button> </body> <script src="/static/jquery-3.2.1.js"></script> <script> function func1(){ //-------------第一步:创建并封装formdata对象------------------------------------ // 创建 FormData对象 var fdata_obj = new FormData(); // 把用户输入的 user值提取出来,赋值给FormData对象 var user = $("#user").val(); fdata_obj.append('user', user ); // 把用户传入的文件对象提取出来,赋值给FormData对象 var file_obj = $("#img")[0].files[0]; fdata_obj.append('img', file_obj); //----------------------------------------------------------------------------- //-------------第二步:通过XMLHttpResponse方式发送formdata对象-------------------- // 创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); // onreadystatechange表示状态每改变一次,函数就被触发执行一次 xhr.onreadystatechange = function () { // 发挥回调函数的功能 if (xhr.readyState == 4) { // 接收完毕服务器返回的数据 console.log(xhr.responseText); } }; xhr.open('GET', '/ajax1.html?p=222'); xhr.send(fdata_obj); // 发送formdata对象 } //--------------------------------------------------------------------------------- </script> </html>
2、ajax方式
ajax底层是基于XMLHttpResponse的。
def upload4(request): if request.method == 'GET': return render(request, 'upload4.html') else: print(request.POST) user = request.POST.get('user') img = request.FILES.get('img') # 获取到的是一个文件对象 f = open(img.name, 'wb') # 服务器端创建一个文件f for line in img.chunks(): f.write(line) f.close() return HttpResponse('上传成功!')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 会员姓名:<input id="user" type="text"><br> 会员头像:<input id="img" type="file"><br> <button id="btn" onclick="func1()">提交</button> </body> <script src="/static/jquery-3.2.1.js"></script> <script> function func1(){ //-------------第一步:创建并封装formdata对象--------------------- // 创建 FormData对象 var fdata_obj = new FormData(); // 把用户输入的 user值提取出来,赋值给FormData对象 var user = $("#user").val(); fdata_obj.append('user', user ); // 注意添加值的写法 // 把用户传入的文件对象提取出来,赋值给FormData对象 var file_obj = $("#img")[0].files[0]; fdata_obj.append('img', file_obj); //-------------------------------------------------------------- //-------------第二步:通过ajax发送formdata对象--------------------- $.ajax({ url: '/upload4.html', type:"POST", data:fdata_obj, // 发送formdata对象 success:function(arg){ console.log(arg) }, // 通过ajax传文件,必须设置以下两个参数: processData: false, // tell jQuery not to process the data contentType: false // tell jQuery not to set contentType }); //--------------------------------------------------------------- } </script> </html>
补充:
(1)对上传按钮进行美化
原理:真正上传文件的input框的opacity调成0,与自定义的好看的按钮下叠加。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 好看的上传按钮 <form action="/upload2.html", method="POST" enctype="multipart/form-data"> <input type="text" name="user"> <div style="position:relative"> <a>好看的上传按钮</a> <input type="file" name="img" style="opacity:0.2;position:absolute;top:0;left:0"> <!--opacity调成0,与好看的按钮下叠加--> </div> <input type="submit" name="提交"> {% csrf_token %} </form> </body> </html> html
代码文档:day61-文件上传