方式一:通過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)
1 # 方法 2 a. void open(String method,String url,Boolen async) 3 用於創建請求 4 5 參數: 6 method: 請求方式(字符串類型),如:POST、GET、DELETE... 7 url: 要請求的地址(字符串類型) 8 async: 是否異步(布爾類型) 9 10 b. void send(String body) 11 用於發送請求 12 13 參數: 14 body: 要發送的數據(字符串類型) 15 16 c. void setRequestHeader(String header,String value) 17 用於設置請求頭 18 19 參數: 20 header: 請求頭的key(字符串類型) 21 vlaue: 請求頭的value(字符串類型) 22 23 d. String getAllResponseHeaders() 24 獲取所有響應頭 25 26 返回值: 27 響應頭數據(字符串類型) 28 29 e. String getResponseHeader(String header) 30 獲取響應頭中指定header的值 31 32 參數: 33 header: 響應頭的key(字符串類型) 34 35 返回值: 36 響應頭中指定的header對應的值 37 38 f. void abort() 39 40 終止請求 41 42 # 屬性 43 a. Number readyState 44 狀態值(整數) 45 46 詳細: 47 0-未初始化,尚未調用open()方法; 48 1-啟動,調用了open()方法,未調用send()方法; 49 2-發送,已經調用了send()方法,未接收到響應; 50 3-接收,已經接收到部分響應數據; 51 4-完成,已經接收到全部響應數據; 52 53 b. Function onreadystatechange 54 當readyState的值改變時自動觸發執行其對應的函數(回調函數) 55 56 c. String responseText 57 服務器返回的數據(字符串類型) 58 59 d. XmlDocument responseXML 60 服務器返回的數據(Xml對象) 61 62 e. Number states 63 狀態碼(整數),如:200、404... 64 65 f. String statesText 66 狀態文本(字符串),如:OK、NotFound...
<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>
