Ajax向后台传入File类型参数
本文内容如下:
一. FormData简介
二. Ajax使用FormData上传文件
三. Ajax使用FormData上传多个文件
四. Ajax使用FormData上传文件综合拓展
一. FormData简介
参考: https://segmentfault.com/a/1190000006716454
https://www.cnblogs.com/jpfss/p/8960806.html
1. 概述
FormData类型其实是在XMLHttpRequest 2级定义的,它是为序列化表以及创建与表单格式相同的数据(当然是用于XHR传输)提供便利。
2. 构造函数
创建一个formData对象实例有几种方式
1、创建一个空对象
实例
var formData = new FormData();
此时可以调用append()方法来添加数据
2、使用已有的表单来初始化一个对象实例
假如现在页面已经有一个表单
<form id="myForm" action="" method="post"> <input type="text" name="name">名字 <input type="password" name="psw">密码 <input type="submit" value="提交"> </form>
我们可以使用这个表单元素作为初始化参数,来实例化一个formData对象
// 获取页面已有的一个form表单 var form = document.getElementById("myForm"); // 用表单来初始化 var formData = new FormData(form); // 我们可以根据name来访问表单中的字段 var name = formData.get("name"); // 获取名字 var psw = formData.get("psw"); // 获取密码
// 当然也可以在此基础上,添加其他数据 formData.append("token","kshdfiwi3rh");
注: 通过 FormData.append()方法赋给字段的值若是数字会被自动转换为字符(字段的值可以是一个Blob对象,一个File对象,或者一个字符串,剩下其他类型的值都会被自动转换成字符串).
3. 操作方法
首先,我们要明确formData里面存储的数据形式,一对key/value组成一条数据,key是唯一的,一个key可能对应多个value。如果是使用表单初始化,每一个表单字段对应一条数据,它们的HTML name属性即为key值,它们value属性对应value值。
key | value |
---|---|
k1 | [v1,v2,v3] |
k2 | v4 |
3.1 获取值
我们可以通过get(key)/getAll(key)来获取对应的value
formData.get("name"); // 获取key为name的第一个值 formData.getAll("name"); // 返回一个数组,获取key为name的所有值
3.2 添加数据
我们可以通过append(key, value)来添加数据,如果指定的key不存在则会新增一条数据,如果key存在,则添加到数据的末尾
formData.append("k1", "v1"); formData.append("k1", "v2"); formData.append("k1", "v1"); formData.get("k1"); // "v1" formData.getAll("k1"); // ["v1","v2","v1"]
3.3 设置修改数据
我们可以通过set(key, value)来设置修改数据,如果指定的key不存在则会新增一条,如果存在,则会修改对应的value值。
formData.append("k1", "v1"); formData.set("k1", "1"); formData.getAll("k1"); // ["1"]
3.4 判断是否该数据
有的浏览器未实现has()的方式,使用时需注意
我们可以通过has(key)来判断是否对应的key值
formData.append("k1", "v1"); formData.append("k2",null); formData.has("k1"); // true formData.has("k2"); // true formData.has("k3"); // false
3.5 删除数据
通过delete(key),来删除数据
formData.append("k1", "v1"); formData.append("k1", "v2"); formData.append("k1", "v1"); formData.delete("k1"); formData.getAll("k1"); // []
3.6 遍历
我们可以通过entries()来获取一个迭代器,然后遍历所有的数据,
formData.append("k1", "v1"); formData.append("k1", "v2"); formData.append("k2", "v1"); var i = formData.entries(); i.next(); // {done:false, value:["k1", "v1"]} i.next(); // {done:false, value:["k1", "v2"]} i.next(); // {done:false, value:["k2", "v1"]} i.next(); // {done:true, value:undefined}
可以看到返回迭代器的规则
-
每调用一次next()返回一条数据,数据的顺序由添加的顺序决定
-
返回的是一个对象,当其done属性为true时,说明已经遍历完所有的数据,这个也可以作为判断的依据
-
返回的对象的value属性以数组形式存储了一对key/value,数组下标0为key,下标1为value,如果一个key值对应多个value,会变成多对key/value返回
-
我们也可以通过values()方法只获取value值
formData.append("k1", "v1"); formData.append("k1", "v2"); formData.append("k2", "v1"); var i = formData.values(); i.next(); // {done:false, value:"v1"} i.next(); // {done:fase, value:"v2"} i.next(); // {done:fase, value:"v1"} i.next(); // {done:true, value:undefined}
4. 发送数据
我们可以通过xhr来发送数据
var xhr = new XMLHttpRequest(); xhr.open("post","login"); xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.send(formData);
这种方式可以来实现文件的异步上传。
二. Ajax使用FormData上传文件
1.使用<form>表单初始化FormData对象方式上传文件
HTML代码:
<form id="uploadForm" enctype="multipart/form-data"> <input id="file" type="file" name="file"/> <button id="upload" type="button">upload</button> </form>
javascript代码
$("#upload").click(function () { $.ajax({ url: '/Default/UploadFile', type: 'POST', cache: false, data: new FormData($('#uploadForm')[0]), processData: false, contentType: false, success: function (data) { alert(data.result) } }).fail(function (res) { alert("系统错误") }); });
这里要注意几点:
-
processData
设置为false
。因为data
值是FormData
对象,不需要对数据做处理。<form>
标签添加enctype="multipart/form-data"
属性。cache
设置为false
,上传文件不需要缓存。contentType
设置为false,不设置contentType值,
因为是由<form>
表单构造的FormData
对象,且已经声明了属性enctype="multipart/form-data"
,所以这里设置为false。
上传后,服务器端代码需要使用从查询参数名为file
获取文件输入流对象,因为<input>
中声明的是name="file"
。
后台代码:
[HttpGet] public IActionResult UploadFile() { return View(); } [HttpPost] public async Task<IActionResult> UploadFile(IFormFile file) { string oFileName = Path.GetFileName(file.FileName); if (!string.IsNullOrEmpty(oFileName)) { return Json(new { Result = "Success", Message = "" }); } return Json(new { Result = "Failed", Message = "" }); }
2.使用FormData对象添加字段方式上传文件
HTML代码:
<div id="uploadForm"> <input id="file" type="file" /> <button id="upload" type="button">upload</button> </div>
javascript代码
$("#upload").click(function () { var formData = new FormData(); formData.append('file', $('#file')[0].files[0]); $.ajax({ url: '/Default/UploadFileByFormData', type: 'POST', cache: false, data: formData, processData: false, contentType: false, success: function (data) { alert(data.result) } }).fail(function (res) { alert("系统错误") }); });
这里有几处不一样:
-
append()
的第二个参数应是文件对象,即$('#file')[0].files[0]
。contentType
也要设置为‘false’。
从代码$('#file')[0].files[0]
中可以看到一个<input type="file">
标签能够上传多个文件,
只需要在<input type="file">
里添加multiple
或multiple="multiple"
属性。
后台代码
public async Task<IActionResult> UploadFileByFormData(IFormFile file) { string oFileName = Path.GetFileName(file.FileName); if (!string.IsNullOrEmpty(oFileName)) { return Json(new { Result = "Success", Message = "" }); } return Json(new { Result = "Failed", Message = "" }); }
三. Ajax使用FormData上传多个文件
在<input type="file">
里添加multiple="multiple"
属性,选择文件时,按住Ctrl键或Shift键选择多个文件
HTML代码
<div id="uploadForm"> <input id="file" type="file" multiple="multiple" /> <button id="upload" type="button">upload</button> </div>
javascript代码
<script type="text/javascript"> $("#upload").click(function () { var formData = new FormData(); for (var i = 0; i < $('#file')[0].files.length; i++) { formData.append('files', $('#file')[0].files[i]); } $.ajax({ url: '/Default/UploadFilesByFormData', type: 'POST', cache: false, data: formData, processData: false, contentType: false, success: function (data) { alert(data.message) } }).fail(function (res) { alert("系统错误") }); }); </script>
后台代码
public async Task<IActionResult> UploadFilesByFormData(IFormFile[] files) { string fileNames = ""; for (int i = 0; i < files.Length; i++) { fileNames += files[i].FileName+"; "; } return Json(new { Result = "Success", Message = fileNames }); }
四. Ajax使用FormData上传文件综合拓展
通过在<input type="file">
里添加multiple="multiple"
属性,虽然能够实现一次长传多个文件,但是并不能显示多个文件的文件名,也不能对选中的文件进行删除,新增的操作,以下实例是优化后的多个文件上传。
实现效果如下:
HTML代码:
<table> <tr style="width:100%;"> <td style="width:150px; text-align:right;line-height:40px;"><label style="margin-top:8px;">附件上传:</label></td> <td colspan="3" style="margin-left:50px;text-align:left;line-height:40px;"> <img src="~/images/附件.png" style="height:10%" /> <input id="file" type="file" style="display:none;" onchange="AddFile()" /> <span id="sfile" onclick="document.getElementById('file').click()" style="line-height:40px;color:gray;font-weight:600;"> Add File</span> </td> </tr> </table> <div id="divShowFile"> </div> <button id="upload" type="button" style="margin-left:150px;">upload</button>
<style type="text/css"> #sfile:hover { text-decoration: underline; cursor: pointer; color: blue; } </style>
javascript代码
<script type="text/javascript"> var FileData = new FormData();//保存File文件 var num = 0;//保存file文件id序号 function AddFile() { var isonly = "T"; var fileid = "file" + num; var pid = "p" + num; var lblid = "lbl" + num; var filePath = $('#file').val(); if (filePath.trim() != "") {//选择了上传文件 //遍历FileData,看是否有重复数据 $(".lblfile").each(function () { if (filePath == $(this).text()) { isonly = "F"; alert("File has upload"); } }); if (isonly == "T") { //将上传的文件添加到全局变量FileData中 FileData.append(fileid, $('#file')[0].files[0]); //添加P标签,显示上传文件名 var p = "<p id=" + pid + " style='margin-left:140px;'> <label class='lblfile' id=" + lblid + " Title=" + fileid + ">" + filePath + "</label> "; p += "<img src='/images/删除.png' style='width:1%;cursor:pointer;' onclick='DeleteFile(\"" + fileid + "\",\"" + pid + "\")'>"; p += "</p>"; $("#divShowFile").append(p); num++; } } } function DeleteFile(fileid, pid) { //将删除的文件从全局变量FileData中删除 FileData.delete(fileid); //删除对应的P标签 $("#" + pid).empty(); } $("#upload").click(function () { debugger; if ($(".lblfile").length == 0) { alert("请加入上传文件"); } var formData = new FormData(); $(".lblfile").each(function () { formData.append("files", FileData.get($(this)[0].title)); }); $.ajax({ url: '/File/UploadFiles', type: 'POST', cache: false, data: formData, processData: false, contentType: false, success: function (data) { alert(data.result) } }).fail(function (res) { alert("系统错误") }); }); </script>
后台代码:
此处是将上传的批量File文件保存到Azure Blob,上传文件到Azure Blob可以看我之前写的博客 https://www.cnblogs.com/suflowers1700218/p/13606425.html
#region[文件上传] public IActionResult Index() { return View(); } [HttpPost] public async Task<IActionResult> UploadFiles(IFormFile[] files) { try { for (int i = 0; i < files.Length; i++) {
//上传文件到Azure Blob string oFileName = Path.GetFileName(files[i].FileName);//获取文件名 string fileExtension = Path.GetExtension(oFileName).ToLower();//获取文件扩展名 string AzureFilePath = $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}" + fileExtension; await AzureHelp.FileUploadAsync(AzureFilePath, files[i].OpenReadStream(), StorageConnectionstring, ContainerName); } return Json(new { Result = "Success", Message = "" }); } catch (Exception ex) { return Json(new { Result = "Failed", Message = ex.Message }); } } #endregion