方式一:通过form表单中,html input 标签的“file”完成
# 前端代码uoload.html <form method="post" action="/upload/" enctype="multipart/form-data"> <input id="user" type="text" name="user" /> <input id=\'img\' type="file" name="img" /> <input type="submit" /> </form>
# 后端代码 def upload(request): if request.method == \'POST\': ret = {\'status\': False, \'data\': None, \'error\': None} try: user = request.POST.get(\'user\') img = request.FILES.get(\'img\') f = open(os.path.join(\'static\', img.name), \'wb\') for chunk in img.chunks(chunk_size=1024): f.write(chunk) ret[\'status\'] = True ret[\'data\'] = os.path.join(\'static\', img.name) except Exception as e: ret[\'error\'] = e finally: f.close() return HttpResponse(json.dumps(ret)) return render(request, \'upload.html\')
方法二:利用XmlHttpRequest对象,发送原生的Ajax请求
(这种方法不能发送文件,需要依赖另外一个对象FormData)
# 方法 a. void open(String method,String url,Boolen async) 用于创建请求 参数: method: 请求方式(字符串类型),如:POST、GET、DELETE... url: 要请求的地址(字符串类型) async: 是否异步(布尔类型) b. void send(String body) 用于发送请求 参数: body: 要发送的数据(字符串类型) c. void setRequestHeader(String header,String value) 用于设置请求头 参数: header: 请求头的key(字符串类型) vlaue: 请求头的value(字符串类型) d. String getAllResponseHeaders() 获取所有响应头 返回值: 响应头数据(字符串类型) e. String getResponseHeader(String header) 获取响应头中指定header的值 参数: header: 响应头的key(字符串类型) 返回值: 响应头中指定的header对应的值 f. void abort() 终止请求 # 属性 a. Number readyState 状态值(整数) 详细: 0-未初始化,尚未调用open()方法; 1-启动,调用了open()方法,未调用send()方法; 2-发送,已经调用了send()方法,未接收到响应; 3-接收,已经接收到部分响应数据; 4-完成,已经接收到全部响应数据; b. Function onreadystatechange 当readyState的值改变时自动触发执行其对应的函数(回调函数) c. String responseText 服务器返回的数据(字符串类型) d. XmlDocument responseXML 服务器返回的数据(Xml对象) e. Number states 状态码(整数),如:200、404... f. String statesText 状态文本(字符串),如:OK、NotFound... XmlHttpRequest对象的主要属性和方法
<input type="button" value="XMLHttpRequest按钮" onclick="XHRAjax();"> <script> function XHRAjax() { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { # 回调函数--每当请求变化时,都会被触发,比如:创建、open、send、recv等。 if(xhr.readyState == 4){ # 仅当服务器数据全部返回时触发 var data = xhr.responseText; console.log(data) } }; // GET请求 // xhr.open(\'GET\', \'/xhr_ajax?p=123\'); // xhr.send(); // POST请求 xhr.open(\'POST\', \'/xhr_ajax/\'); # 这里的URL必须加斜杠结尾。 发送post请求的时候必须携带请求头 xhr.setRequestHeader(\'Content-Type\', \'application/x-www-form-urlencoded; charset-UTF-8\'); // 发送请求 xhr.send(\'n1=1;n2=2;\'); }; </script>
def ajax(request): import time current_time = time.time() return render(request, \'ajax.html\', {\'current_time\': current_time})
上述的内容,已经可以完成原生ajax的发送。 如果需要发送文件,则需要借助于FormData对象.下边介绍一下FormData的简单用法
# 前端代码 <input type="button" value="XMLHttpRequest-FormData按钮" onclick="XHRAjaxForm();">
# 后端代码: 基于FormData对象发送请求 function XHRAjaxForm() { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if(xhr.readyState == 4){ var data = xhr.responseText; console.log(data) } }; xhr.open(\'POST\', \'/xhr_ajax/\'); // 发送请求 var form = new FormData(); # 创建FormData对象 form.append(\'user\', \'alex\'); form.append(\'pwd\', \'123\'); xhr.send(form); };
上面的例子,简单的介绍了FormData的用法 。下边的案例介绍如何使用formdate对象来上传文件
前端部分 <a onclick="uploadfile1();" style="cursor: pointer; display: inline-block;background-color: aqua">XMLHttpRequet上传</a> # JS部分 <script> function uploadfile1() { var form = new FormData(); form.append(\'user\', document.getElementById(\'user\').value); var fileobj = document.getElementById(\'img\').files[0]; form.append(\'img\', fileobj); var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if(xhr.readyState == 4){ var data = xhr.responseText; console.log(data) } }; xhr.open(\'post\', \'/upload/\', true) xhr.send(form); } </script>
方法三:利用JQuery Ajax + FormData进行文件上传
Jquery转换为dom对象:$("#img")[0].files[0]; 其中$("#img")是jquery对象, $("#img")[0]是dom对象
<a onclick="uploadFile2();" style="cursor: pointer; display: inline-block;background-color: aqua">JQuery-Ajax上传</a> <script> function uploadFile2() { var fileobj = $("#img")[0].files[0]; console.log(fileobj); var form = new FormData(); form.append("img", fileobj); form.append("uesr", \'alex\'); $.ajax({ type: \'POST\', url: \'/upload/\', data: form, processData: false, # 告诉jquery要传输data对象 contentType: false, # 告诉jquery不需要增加请求头对于contentType的设置 success: function (arg) { console.log(arg) } }) } </script>
方法四:基于Iframe 实现伪Ajax 上传文件
<a onclick="uploadFile3();" style="cursor: pointer; display: inline-block;background-color: aqua">IFrame上传</a> <script> function uploadFile3() { // target 是个name的属性值,而不是id $("#container").find(\'img\').remove(); document.getElementById("my_iframe").onload = callback; document.getElementById(\'fo\').target = \'my_iframe\'; document.getElementById(\'fo\').submit(); } function callback() { var t = $(\'#my_iframe\').contents().find(\'body\').text(); var json_data = JSON.parse(t); console.log(json_data); if(json_data.status){ // 上传成功 var tag = document.createElement(\'img\'); tag.src = "/" + json_data.data; tag.className = \'img\'; $(\'#container\').append(tag); }else{ // 上传失败 console.log(status.error); } } </script>
不是所有的浏览器都可以兼容FormData对象。为了兼容性,引出iframe 的用法。
iframe可以建立一个通道发送请求,利用iframe局部刷新的特性实现目标。
# 前端代码 <iframe name="my_iframe" style="display: none;" src=""></iframe> # 这里使用的是name标签,和id标签无关 <a onclick="uploadFile3();" style="cursor: pointer; display: inline-block;background-color: aqua">IFrame上传</a> <div id="container"></div> <script> function uploadFile3() { // target 是个name的属性值,而不是id $("#container").find(\'img\').remove(); document.getElementById("my_iframe").onload = callback; # 通过js手动绑定一个事件 document.getElementById(\'fo\').target = \'my_iframe\'; # 这里target对应的是一个iframe 的name属性 document.getElementById(\'fo\').submit(); } function callback() { var t = $(\'#my_iframe\').contents().find(\'body\').text(); var json_data = JSON.parse(t); console.log(json_data); if(json_data.status){ // 上传成功 var tag = document.createElement(\'img\'); tag.src = "/" + json_data.data; tag.className = \'img\'; $(\'#container\').append(tag); }else{ // 上传失败 console.log(status.error); } } </script>