在一個網站中,上傳檔案也是相當重要的功能,諸如匯入或是更新用戶內容經常會用到。
首先,先解決CSRF跨域請求的安全機制。
方式一:
在form標籤中,加入 {% csrf_token %}
<form id="form" action="/userinfo/" method="POST"> {% csrf_token %} <div> <input type="text" name="username" /> </div> <input type="submit" value="提交"/> </form>
方式二:
如果使用jquery ajax提交,
<script src="/static/jquery.cookie.js" charset="utf-8"></script> $.ajax({ url:"/bookstore/file_put/", type:"POST", headers:{ "X-CSRFToken":$.cookie('csrftoken') }, })
方式三:
在所有使用POST操作的ajax前面,插入以下代碼。
這段代碼會在送出請求前,將csrf的字串放入請求頭中。你也不用在每個ajax請求中,加入 headers:{"X-CSRFToken":$.cookie('csrftoken')} 這段代碼了。
<script src="/static/jquery-3.4.1.js" charset="utf-8"></script> var csrftoken = $.cookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); //用來判斷是否非POST方法 } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type /*請求方式*/ ) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
在學會處理csrf跨域請求後,我們就可以開始進入檔案上傳的內容了。
最基本的檔案上傳就是使用form提交
<form action="/file_put/" method="POST" enctype="multipart/form-data"> {% csrf_token %} 姓名 <input type="text" name="user"> 文件 <input type="file" name="file_obj"> <input type="submit" /> </form>
因為一般的form提交是以urlcode的格式提交數據,但是上傳檔案需要用不同的格式上傳,因此需要使用 enctype="multipart/form-data" 來告訴瀏覽器這次提交的事檔案類型的數據。
瀏覽器上傳以後,就要由後台接收數據了,瀏覽器會將數據提交到form action 中所定的url中。
後台view就要使用這個url定義一個處理的函數。
from app import settings def file_put(request): print(request.POST,request.FILES) file_obj = request.FILES.get('file_obj') #文件物件有一個name屬性,獲取文件名稱字符串 path = os.path.join(settings.BASE_DIR,"media",file_obj.name) #將上傳目的文件夾join到django目錄中 with open(path,'wb') as f: for line in file_obj: f.write(line) #另一種寫法,使用chunks()方法 #for item in file_obj.chunks(): # f.write(item); return HttpResponse('OK')
使用基於jquery ajax的檔案上傳
<form> {% csrf_token %} 姓名 <input type="text" id="user"> 文件 <input type="file" name="file_obj" id="file"> <input type="button" class="filebtn" value="upload file"/> </form>
$('.filebtn').click(function(){ //在javascript中榜定一個事件 //使用FormData處理formdata格式 var formdata = new FormData(); var file = document.getElementByID("file").files[0]; //在formdata加入數據 formdata.append("file_obj",file); formdata.append("user",$('#user').val()); $.ajax({ url:"/bookstore/file_put/", type:"POST", data:formdata, processData: false, //告訴瀏覽器不要特別處理數據 contentType: false, success:function(data){ console.log(data); }, }); });
使用原生ajax的檔案上傳:
function xhrSubmit() { // $("#file")[0] var file_obj = document.getElementById("file").files[0]; var fd = new FormData(); fd.append('username', 'root'); fd.append(file_obj', file_obj); var xhr = new XMLHttpRequest(); xhr.open("POST", '/file_put/', true); xhr.send(fd); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { var obj = JSON.parse(xhr.responseText); console.log(obj); }; }; }
基於iframe的檔案上傳:
<form action="/app01/upload_file/" method="POST" enctype="multipart/form-data" target="ifml"> {% csrf_token %} <iframe id="ifml" name="ifml"></iframe> <input type="file" name="fafafa"/> <input type="submit" name="iframeSubmit" onclick="iframeSubmit();"/> </form> <div id="preview"><!--圖片預覽--> </div>
function iframeSubmit() { $('#ifml').load(function(){ var text = $('#ifml').contents().find('body').text(); var obj = JSON.parse(text); $('#preview').empty(); var imgTag = document.createElement('img'); imgTag.src = "/" + obj.data; print(obj.data); $('#preview').append(imgTag); }); } function onChangeSubmit(){ $('#ifml').load(function(){ var text = $('#ifml').contents().find('body').text(); var obj = JSON.parse(text); $('#preview').empty(); var imgTag = document.createElement('img'); imgTag.src = "/" + obj.data; print(obj.data); $('#preview').append(imgTag); }); $('#ifml').submit(); }