个人实现方式:
html代码
js代码:
$(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代码
@required_login(redirect="/build/login/")@csrf_exemptdef 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()
以下是引用的别人和官方的文章
########################################################################
用到两个对象
第一个对象:FormData
第二个对象:XMLHttpRequest
目前新版的Firefox 与 Chrome 等支持HTML5的浏览器完美的支持这两个对象,但IE9尚未支持 FormData 对象,还在用IE6 ? 只能仰天长叹....
有了这两个对象,我们可以真正的实现Ajax方式上传文件。
示例代码:
Html5 Ajax 上传文件
很简洁的代码,便可以达到Ajax方式上传文件,上面的代码中使用<input type="file" />这种传统的选择文件的方法产生文件对象,HTML5还支持使用多种更灵活的方式,如拖拽文件到指定的元素上产生。
Ajax已成功上传文件,但这时我们会想到一个问题,如何显示进度条?带着这个问题,脑子会想到,Flash? 浏览器插件?。
NO,现在不需要这些东西了。
开始着手,先做一个进度条,进度条也很简单,使用HTML5 新加的标签:
这个在浏览器中便会呈现了一个进度条,现在我们要做的就是在上传的时候,实时的去改变它的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,带进度显示:
Html5 Ajax 上传文件
后台接收文件的程序可以是任何语言(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); }
以上引用自:
########################################################################
使用FormData对象
利用对象,你可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest
发送这个"表单".
创建一个FormData对象
你可以先创建一个空的FormData
对象,然后使用方法向该对象里添加字段,如下:
var oMyForm = new FormData(); oMyForm.append("username", "Groucho"); oMyForm.append("accountnum", 123456); // 数字123456被立即转换成字符串"123456" // fileInputElement中已经包含了用户所选择的文件 oMyForm.append("userfile", fileInputElement.files[0]); var oFileBody = 'hey!'; // 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"的值都包含了一个文件.通过 方法赋给字段"accountnum"的数字被自动转换为字符(字段的值可以是一个对象,一个对象,或者一个字符串,剩下其他类型的值都会被自动转换成字符串).
在该例子中,我们创建了一个名为oMyForm的FormData
对象,该对象中包含了名为"username", "accountnum", "userfile" 以及 "webmasterfile"的字段名,然后使用XMLHttpRequest
的方法把这些数据发送了出去."webmasterfile"字段的值不是一个字符串,还是一个对象.
使用HTML表单来初始化一个FormData对象
可以用一个已有的元素来初始化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对象发送文件
你还可以使用FormData
来发送二进制文件.首先在HTML中要有一个包含了文件输入框的form元素:
Stash the file!
然后你就可以使用下面的代码来异步的上传用户所选择的文件:
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.
"; } }; oReq.send(oData); }
你还可以不借助HTML表单,直接向对象中添加一个对象或者一个对象:
data.append("myfile", myBlob);
如果FormData对象中的某个字段值是一个对象,则在发送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,地址:
#########################################################################
通过传统的form表单提交的方式上传文件:
Html代码
不过传统的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+。 参见: |
这里只展示一个通过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.
"; } }; oReq.send(oData);
参见:
使用FormData,进行Ajax请求并上传文件
这里使用JQuery,但是老版本的JQuery比如1.2是不支持的,最好使用2.0或更新版本:
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); } }); }
以上引用自: