我的實現方式:javascript
html代碼php
<form id="uploadForm" class="smart-form" novalidate="novalidate" method="post" action=""> {% csrf_token %} <div class="row"> <section style="padding-left:15px;padding-right:15px;"> <label class="label">請選擇上傳的配置文件<span><font size="3px" color="#FF0000">*</font></span></label> <div class="input input-file"> <span class="button"><input type="file" id="uoload" name="uoload" onchange="this.parentNode.nextSibling.value = this.value">Browse</span><input type="text" readonly=""> </div> </section> </div> <footer style="height:30px"> <button class="btn btn-primary" type="submit"> 確認保存 </button> </footer> </form>
js代碼:css
$(document).ready(function() { //alert($("#file").parent().get(0).tagName); var uploadForm = $("#uploadForm").validate({ // Rules for form validation rules : { uoload :{ required : true } }, // Messages for form validation messages : { uoload :{ required : '上傳文件不能爲空' } }, submitHandler: function(form){ //若是不加[0]:Argument 1 of FormData.constructor does not implement interface HTMLFormElem //$('form') returns a jQuery object, but we need to pass a HTML element to FormData. `[0]` does that for us. It is the same as calling $('form').get(0) var fd = new FormData($("#uploadForm")[0]); //能夠傳額外的參數 fd.append("CustomField", "This is some extra data"); $.ajax({ url: "/build/configAdd/", type: "POST", data: fd, processData: false, // 告訴jQuery不要去處理髮送的數據 contentType: false, // 告訴jQuery不要去設置Content-Type請求頭 error: function(msg) { closeMyDialog($("#setAddId")); showSuccessMsg("添加配置失敗"); }, success: function(msg){ closeMyDialog($("#setAddId")); showSuccessMsg(msg); } }); }, // Do not change code below //modified by yf 2016_06_17 errorPlacement : function(error, element) { if("SPAN" == element.parent().get(0).tagName){ error.insertAfter(element.parent().next()); error.css("color","#D56161"); error.css("font-size","11px"); error.css("line-height","15px"); error.css("font-style","normal"); }else{ error.insertAfter(element.parent()); } } }); })
後臺python代碼html
@required_login(redirect="/build/login/") @csrf_exempt def configAddHandler(request): if request.method == "GET": return render(request, 'auto_config/configAdd.html') elif request.method == "POST": buf = request.FILES.get('uoload', None) if buf: f = buf.read() print type(f) BASE_DIR = os.path.dirname(__file__) #保存上傳的excel,以作歷史查詢 try: save_file(BASE_DIR, str(buf), f) return HttpResponse("上傳成功") except: return HttpResponse("上傳失敗") else: return HttpResponse("上傳失敗") def mkdir(path): # 去除左右兩邊的空格u path=path.strip() # 去除尾部 \符號 path=path.rstrip("\\") if not os.path.exists(path): os.makedirs(path) return path #工具函數,保存上傳的文件 def save_file(path, file_name, data): if data == None: return mkdir(path) if(not path.endswith("/")): path=path+"/" fileObj=open(path+file_name, "wb") fileObj.write(data) fileObj.flush() fileObj.close()
如下是引用的別人和官方的文章java
########################################################################python
用到兩個對象web
第一個對象:FormDataajax
第二個對象:XMLHttpRequest瀏覽器
目前新版的Firefox 與 Chrome 等支持HTML5的瀏覽器完美的支持這兩個對象,但IE9還沒有支持 FormData 對象,還在用IE6 ? 只能仰天長嘆....服務器
有了這兩個對象,咱們能夠真正的實現Ajax方式上傳文件。
示例代碼:
<!DOCTYPE html> <html> <head> <title>Html5 Ajax 上傳文件</title> <script type="text/javascript"> function UpladFile() { var fileObj = document.getElementByIdx_x_x("file").files[0]; // 獲取文件對象 var FileController = "../file/save"; // 接收上傳文件的後臺地址 // FormData 對象 var form = new FormData(); form.append("author", "hooyes"); // 能夠增長表單數據 form.append("file", fileObj); // 文件對象 // XMLHttpRequest 對象 var xhr = new XMLHttpRequest(); xhr.open("post", FileController, true); xhr.onload = function () { alert("上傳完成!"); }; xhr.send(form); } </script> </head> <body> <input type="file" id="file" name="myfile" /> <input type="button" onclick="UpladFile()" value="上傳" /> </body> </html>
很簡潔的代碼,即可以達到Ajax方式上傳文件,上面的代碼中使用<input type="file" />這種傳統的選擇文件的方法產生文件對象,HTML5還支持使用多種更靈活的方式,如拖拽文件到指定的元素上產生。
Ajax已成功上傳文件,但這時咱們會想到一個問題,如何顯示進度條?帶着這個問題,腦子會想到,Flash? 瀏覽器插件?。
NO,如今不須要這些東西了。
開始着手,先作一個進度條,進度條也很簡單,使用HTML5 新加的標籤:
<progress id="progressBar" value="0" max="100"> </progress>
這個在瀏覽器中便會呈現了一個進度條,如今咱們要作的就是在上傳的時候,實時的去改變它的Value值,而後進度顯示的問題便交給它了。
咱們的服務器端無需修改,只須要在JS中XHR對象加一個事件。
xhr.upload.addEventListener("progress", progressFunction, false)
progressFunction 被調用的時候會傳進一個事件對象,這個對象有兩個屬性,一個就是loaded 一個是total ,分別表明,已上傳的值,和總要上傳的值。
這正是咱們須要的,因此這個方法,能夠這樣寫:
function progressFunction(evt) { var progressBar = document.getElementByIdx_x_x("progressBar"); if (evt.lengthComputable) { progressBar.max = evt.total; progressBar.value = evt.loaded; } }
這樣即可以完成,上傳進度顯示了。
以下針對上面的第一個示例代碼,作一個調整:
示例代碼2,帶進度顯示:
<!DOCTYPE html> <html> <head> <title>Html5 Ajax 上傳文件</title> <script type="text/javascript"> function UpladFile() { var fileObj = document.getElementByIdx_x_x("file").files[0]; // js 獲取文件對象 var FileController = "../file/save"; // 接收上傳文件的後臺地址 // FormData 對象 var form = new FormData(); form.append("author", "hooyes"); // 能夠增長表單數據 form.append("file", fileObj); // 文件對象 // XMLHttpRequest 對象 var xhr = new XMLHttpRequest(); xhr.open("post", FileController, true); xhr.onload = function () { // alert("上傳完成!"); }; xhr.upload.addEventListener("progress", progressFunction, false); xhr.send(form); } function progressFunction(evt) { var progressBar = document.getElementByIdx_x_x("progressBar"); var percentageDiv = document.getElementByIdx_x_x("percentage"); if (evt.lengthComputable) { progressBar.max = evt.total; progressBar.value = evt.loaded; percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%"; } } </script> </head> <body> <progress id="progressBar" value="0" max="100"> </progress> <span id="percentage"></span> <br /> <input type="file" id="file" name="myfile" /> <input type="button" onclick="UpladFile()" value="上傳" /> </body> </html>
後臺接收文件的程序能夠是任何語言(C#,PHP,Python 等)編寫的,上述例子使用C#
很簡單,無需爲這個進度條作任何改動。
var flist = Request.Files; for (int i = 0; i < flist.Count; i++) { string FilePath = "E:\\hooyes\\Files\\"; var c = flist[i]; FilePath = Path.Combine(FilePath, c.FileName); c.SaveAs(FilePath); }
以上引用自:http://blog.sina.com.cn/s/blog_5d64f7e3010127ns.html
########################################################################
利用FormData
對象,你可使用一系列的鍵值對來模擬一個完整的表單,而後使用XMLHttpRequest
發送這個"表單".
你能夠先建立一個空的FormData
對象,而後使用append()
方法向該對象裏添加字段,以下:
var oMyForm = new FormData(); oMyForm.append("username", "Groucho"); oMyForm.append("accountnum", 123456); // 數字123456被當即轉換成字符串"123456" // fileInputElement中已經包含了用戶所選擇的文件 oMyForm.append("userfile", fileInputElement.files[0]); var oFileBody = '<a id="a"><b id="b">hey!</b></a>'; // Blob對象包含的文件內容 var oBlob = new Blob([oFileBody], { type: "text/xml"}); oMyForm.append("webmasterfile", oBlob); var oReq = new XMLHttpRequest(); oReq.open("POST", "http://foo.com/submitform.php"); oReq.send(oMyForm);
注: 字段"userfile"和"webmasterfile"的值都包含了一個文件.經過 FormData.append()
方法賦給字段"accountnum"的數字被自動轉換爲字符(字段的值能夠是一個Blob
對象,一個File
對象,或者一個字符串,剩下其餘類型的值都會被自動轉換成字符串).
在該例子中,咱們建立了一個名爲oMyForm的FormData
對象,該對象中包含了名爲"username", "accountnum", "userfile" 以及 "webmasterfile"的字段名,而後使用XMLHttpRequest
的send()
方法把這些數據發送了出去."webmasterfile"字段的值不是一個字符串,仍是一個Blob
對象.
能夠用一個已有的<form>
元素來初始化FormData對象
,只須要把這個form
元素做爲參數傳入FormData
構造函數便可:
var newFormData = new FormData(someFormElement);
例如:
var formElement = document.getElementById("myFormElement"); var oReq = new XMLHttpRequest(); oReq.open("POST", "submitform.php"); oReq.send(new FormData(formElement));
你還能夠在已有表單數據的基礎上,繼續添加新的鍵值對,以下:
var formElement = document.getElementById("myFormElement"); formData = new FormData(formElement); formData.append("serialnumber", serialNumber++); oReq.send(formData);
你能夠經過這種方式添加一些不想讓用戶編輯的固定字段,而後再發送.
你還可使用FormData
來發送二進制文件.首先在HTML中要有一個包含了文件輸入框的form元素:
<form enctype="multipart/form-data" method="post" name="fileinfo"> <label>Your email address:</label> <input type="email" autocomplete="on" autofocus name="userid" placeholder="email" required size="32" maxlength="64" /><br /> <label>Custom file label:</label> <input type="text" name="filelabel" size="12" maxlength="32" /><br /> <label>File to stash:</label> <input type="file" name="file" required /> </form> <div id="output"></div> <a href="javascript:sendForm()">Stash the file!</a>
而後你就可使用下面的代碼來異步的上傳用戶所選擇的文件:
function sendForm() { var oOutput = document.getElementById("output"); var oData = new FormData(document.forms.namedItem("fileinfo")); oData.append("CustomField", "This is some extra data"); var oReq = new XMLHttpRequest(); oReq.open("POST", "stash.php", true); oReq.onload = function(oEvent) { if (oReq.status == 200) { oOutput.innerHTML = "Uploaded!"; } else { oOutput.innerHTML = "Error " + oReq.status + " occurred uploading your file.<br \/>"; } }; oReq.send(oData); }
你還能夠不借助HTML表單,直接向FormData
對象中添加一個File
對象或者一個Blob
對象:
data.append("myfile", myBlob);
若是FormData對象中的某個字段值是一個Blob
對象,則在發送http請求時,表明該Blob
對象所包含文件的文件名的"Content-Disposition"請求頭的值在不一樣的瀏覽器下有所不一樣,Firefox使用了固定的字符串"blob,"而Chrome使用了一個隨機字符串.
你還可使用jQuery來發送FormData,但必需要正確的設置相關選項
:
var fd = new FormData(document.getElementById("fileinfo")); fd.append("CustomField", "This is some extra data"); $.ajax({ url: "stash.php", type: "POST", data: fd, processData: false,// 告訴jQuery不要去處理髮送的數據 contentType: false // 告訴jQuery不要去設置Content-Type請求頭 });
以上引用MDA,地址:https://developer.mozilla.org/zh-CN/docs/Web/Guide/Using_FormData_Objects
#########################################################################
經過傳統的form表單提交的方式上傳文件:
Html代碼
<form id= "uploadForm" action= "http://localhost:8080/cfJAX_RS/rest/file/upload" method= "post" enctype ="multipart/form-data"> <h1 >測試經過Rest接口上傳文件 </h1> <p >指定文件名: <input type ="text" name="filename" /></p> <p >上傳文件: <input type ="file" name="file" /></p> <p >關鍵字1: <input type ="text" name="keyword" /></p> <p >關鍵字2: <input type ="text" name="keyword" /></p> <p >關鍵字3: <input type ="text" name="keyword" /></p> <input type ="submit" value="上傳"/> </form>
不過傳統的form表單提交會致使頁面刷新,可是在有些狀況下,咱們不但願頁面被刷新,這種時候咱們都是使用Ajax的方式進行請求的:
$.ajax({ url : "http://localhost:8080/STS/rest/user", type : "POST", data : $( '#postForm').serialize(), success : function(data) { $( '#serverResponse').html(data); }, error : function(data) { $( '#serverResponse').html(data.status + " : " + data.statusText + " : " + data.responseText); } });
如上,經過$('#postForm').serialize()能夠對form表單進行序列化,從而將form表單中的全部參數傳遞到服務端。
可是上述方式,只能傳遞通常的參數,上傳文件的文件流是沒法被序列化並傳遞的。
不過現在主流瀏覽器都開始支持一個叫作FormData的對象,有了這個FormData,咱們就能夠輕鬆地使用Ajax方式進行文件上傳了。
關於FormData及其用法
FormData是什麼呢?咱們來看看Mozilla上的介紹。
XMLHttpRequest Level 2添加了一個新的接口
全部主流瀏覽器的較新版本都已經支持這個對象了,好比Chrome 7+、Firefox 4+、IE 10+、Opera 12+、Safari 5+。 參見:https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/FormData |
這裏只展現一個經過from表單來初始化FormData的方式
<form enctype="multipart/form-data" method="post" name="fileinfo">
Js代碼
var oData = new FormData(document.forms.namedItem("fileinfo" )); oData.append( "CustomField", "This is some extra data" ); var oReq = new XMLHttpRequest(); oReq.open( "POST", "stash.php" , true ); oReq.onload = function(oEvent) { if (oReq.status == 200) { oOutput.innerHTML = "Uploaded!" ; } else { oOutput.innerHTML = "Error " + oReq.status + " occurred uploading your file.<br \/>"; } }; oReq.send(oData);
參見:https://developer.mozilla.org/zh-CN/docs/Web/Guide/Using_FormData_Objects
使用FormData,進行Ajax請求並上傳文件
這裏使用JQuery,可是老版本的JQuery好比1.2是不支持的,最好使用2.0或更新版本:
<form id= "uploadForm"> <p >指定文件名: <input type="text" name="filename" value= ""/></p > <p >上傳文件: <input type="file" name="file"/></ p> <input type="button" value="上傳" onclick="doUpload()" /> </form>
Js代碼
function doUpload() { var formData = new FormData($( "#uploadForm" )[0]); $.ajax({ url: 'http://localhost:8080/cfJAX_RS/rest/file/upload' , type: 'POST', data: formData, async: false, cache: false, contentType: false, processData: false, success: function (returndata) { alert(returndata); }, error: function (returndata) { alert(returndata); } }); }