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值。

keyvalue
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}

可以看到返回迭代器的规则

    1. 每调用一次next()返回一条数据,数据的顺序由添加的顺序决定

    2. 返回的是一个对象,当其done属性为true时,说明已经遍历完所有的数据,这个也可以作为判断的依据

    3. 返回的对象的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">里添加multiplemultiple="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%" />&nbsp;
                <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>  &nbsp;";
                    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

 

posted @ 2021-01-06 14:44  EnjoyToday  阅读(5158)  评论(0编辑  收藏  举报