文件各种上传,离不开的表单

文件各种上传,离不开的表单,第1张

概述作为程序员的我们,经常会要用到文件的上传和下载功能。到了需要用的时候,各种查资料。有木有..有木有...。为了方便下次使用,这里来做个总结和备忘。利用表单实现文件上传最原始、最简单、最粗暴的文件上传。前端代码://方式1<form action="/Home/SaveFile1" method="post" enctype="multipart/form-data"><input type="file" class="file1" name="file1" /><button type="submit" class="but1">上传</button></form>【注意】1、需要post提交2、enctype="multipart/form-data" (传输文件)3、需要提交的表单元素需要设置 name 属性后台代码:public ActionResult SaveFile1(){if (Request.Files.Count > 0){Request.Files[0].SaveAs(Server.MapPath("~/App_Data/") + Request.Files[0].FileName);return Content("保存成功");}return Content("没有读到文件");}表单异步上传(jquery.form插件)虽然上面的方式简单粗暴,但是不够友好。页面必然会刷新。难以实现停留在当前页面,并给出文件上传成功的提示。随着时间的流逝,技术日新月异。ajax的出现,使得异步文件提交变得更加容易。下面我们利用jquery.form插件来实现文件的异步上传。首先我们需要导入jquery.js和jquery.form.js前端代码:<form id="form2" action="/Home/SaveFile2" method="post" enctype="multipart/form-data"><input type="file" class="file1" name="file1" /><button type="submit" class="but1">上传1</button><button type="button" class="but2">上传2</button></form>//方式2(通过ajaxForm绑定ajax *** 作)$(function () {$('#form2').ajaxForm({success: function (responseText) {alert(responseText);}});});//方式3(通过ajaxSubmit直接执行ajax *** 作)$(function () {$(".but2").click(function () {$('#form2').ajaxSubmit({success: function (responseText) {alert(responseText);}});});});后台代码:public string SaveFile2(){if (Request.Files.Count > 0){Request.Files[0].SaveAs(Server.MapPath("~/App_Data/") + Path.GetFileName(Request.Files[0].FileName));return "保存成功";}return "没有读到文件";}原理:我们很多时候使用了插件,就不管其他三七二十一呢。如果有点好奇心,想想这个插件是怎么实现的。随便看了看源码一千五百多行。我的妈呀,不就是个异步上传吗,怎么这么复杂。难以看出个什么鬼来,直接断点调试下吧。原来插件内部有iframe和FormData不同方式来上传,来适应更多版本浏览器。模拟表单数据上传(FormData)iframe这东西太恶心。我们看到上面可以利用FormData来上传文件,这个是Html 5 才有的。下面我们自己也来试试把。前端代码:<input id="fileinfo" type="file" class="notFormFile" /><button type="button" class="btnNotForm">上传4</button>//方式4$(".btnNotForm").click(function () {var formData = new FormData();//初始化一个FormData对象formData.append("files", $(".notFormFile")[0].files[0]);//将文件塞入FormData$.ajax({url: "/Home/SaveFile2",type: "POST",data: formData,processData: false, // 告诉jQuery不要去处理发送的数据contentType: false, // 告诉jQuery不要去设置Content-Type请求头success: function (responseText) {alert(responseText);}});});后的代码:(不变,还是上例代码)public string SaveFile2(){if (Request.Files.Count > 0){Request.Files[0].SaveAs(Server.MapPath("~/App_Data/") + Path.GetFileName(Request.Files[0].FileName));return "保存成功";}return "没有读到文件";}我们看到,FormData对象也只是在模拟一个原始的表单格式的数据。那有没有可能不利用表单或表单格式来上传文件呢?答案是肯定的。(下面马上揭晓)前端代码:<input type="file" id="file5" multiple><button type="button" class="btnFile5">上传5</button>//方式5$(".btnFile5").click(function () {$.ajax({url: "/Home/SaveFile4",type: "POST",data: $("#file5")[0].files[0],processData: false, // 告诉jQuery不要去处理发送的数据contentType: false, // 告诉jQuery不要去设置Content-Type请求头success: function (responseText) {alert(responseText);}});;});后台代码:public string SaveFile4(){//这里发现只能得到一个网络流,没有其他信息了。(比如,文件大小、文件格式、文件名等)Request.SaveAs(Server.MapPath("~/App_Data/SaveFile4.data") + "", false);return "保存成功";}细心的你发现没有了表单格式,我们除了可以上传文件流数据外,不能再告诉后台其他信息了(如文件格式)。到这里,我似乎明白了以前上传文件为什么非得要用个form包起来,原来这只是和后台约定的一个传输格式而已。其实我们单纯的用jq的ajax传输文本数据的时候,最后也是组装成了form格式的数据,如:$.ajax({data: { "userName": "张三" }分片上传在知道了上面的各种上传之后,我们是不是就满于现状了呢?no,很多时候我们需要传输大文件,一般服务器都会有一定的大小限制。某天,你发现了一个激情小电影想要分享个大家。无奈,高清文件太大传不了,怎么办?我们可以化整为零,一部分一部分的传嘛,也就是所谓的分片上传。前端代码:<input type="file" id="file6" multiple><button type="button" class="btnFile6">分片上传6</button><div class="result"></div>//方式6$(".btnFile6").click(function () {var upload = function (file, skip) {var formData = new FormData();//初始化一个FormData对象var blockSize = 1000000;//每块的大小var nextSize = Math.min((skip + 1) * blockSize, file.size);//读取到结束位置var fileData = file.slice(skip * blockSize, nextSize);//截取 部分文件 块formData.append("file", fileData);//将 部分文件 塞入FormDataformData.append("fileName", file.name);//保存文件名字$.ajax({url: "/Home/SaveFile6",type: "POST",data: formData,processData: false, // 告诉jQuery不要去处理发送的数据contentType: false, // 告诉jQuery不要去设置Content-Type请求头success: function (responseText) {$(".result").html("已经上传了" + (skip + 1) + "块文件");if (file.size <= nextSize) {//如果上传完成,则跳出继续上传alert("上传完成");return;}upload(file, ++skip);//递归调用}});};var file = $("#file6")[0].files[0];upload(file, 0);});后台代码:public string SaveFile6(){//保存文件到根目录 App_Data + 获取文件名称和格式var filePath = Server.MapPath("~/App_Data/") + Request.Form["fileName"];//创建一个追加(FileMode.Append)方式的文件流using (FileStream fs = new FileStream(filePath, File

作为程序员的我们,经常会要用到文件的上传和下载功能。到了需要用的时候,各种查资料。有木有..有木有...。为了方便下次使用,这里来做个总结和备忘。

最原始、最简单、最粗暴的文件上传。前端代码:

//方式1

【注意】

1、需要post提交2、enctype="multipart/form-data" (传输文件)3、需要提交的表单元素需要设置 name 属性

后台代码:

public ActionResult Savefile1(){    if (Request.files.Count > 0)    {        Request.files[0].SaveAs(Server.MapPath("~/App_Data/") + Request.files[0].filename);        return Content("保存成功");    }    return Content("没有读到文件");}

虽然上面的方式简单粗暴,但是不够友好。页面必然会刷新。难以实现停留在当前页面,并给出文件上传成功的提示。随着时间的流逝,技术日新月异。AJAX的出现,使得异步文件提交变得更加容易。下面我们利用jquery.form插件来实现文件的异步上传。首先我们需要导入jquery.Jsjquery.form.Js前端代码:

//方式2(通过AJAXForm绑定AJAX *** 作)$(function () {    $('#form2').AJAXForm({        success: function (responseText) {            alert(responseText);        }    });});

//方式3(通过AJAXsubmit直接执行AJAX *** 作)
$(function () {
$(".but2").click(function () {
$('#form2').AJAXsubmit({
success: function (responseText) {
alert(responseText);
}
});
});
});

后台代码:

public string Savefile2(){    if (Request.files.Count > 0)    {                        Request.files[0].SaveAs(Server.MapPath("~/App_Data/") + Path.Getfilename(Request.files[0].filename));        return "保存成功";    }    return "没有读到文件";}

原理:我们很多时候使用了插件,就不管其他三七二十一呢。如果有点好奇心,想想这个插件是怎么实现的。随便看了看源码一千五百多行。我的妈呀,不就是个异步上传吗,怎么这么复杂。难以看出个什么鬼来,直接断点调试下吧。

iframe这东西太恶心。我们看到上面可以利用FormData来上传文件,这个是HTML 5 才有的。下面我们自己也来试试把。前端代码:

//方式4$(".btnNotForm").click(function () {    var formData = new FormData();//初始化一个FormData对象    formData.append("files",$(".notFormfile")[0].files[0]);//将文件塞入FormData    $.AJAX({        url: "/Home/Savefile2",type: "POST",data: formData,processData: false,// 告诉jquery不要去处理发送的数据        ContentType: false,// 告诉jquery不要去设置Content-Type请求头        success: function (responseText) {            alert(responseText);        }    });});

后的代码:(不变,还是上例代码)

public string Savefile2(){    if (Request.files.Count > 0)    {                        Request.files[0].SaveAs(Server.MapPath("~/App_Data/") + Path.Getfilename(Request.files[0].filename));        return "保存成功";    }    return "没有读到文件";}

我们看到,FormData对象也只是在模拟一个原始的表单格式的数据。那有没有可能不利用表单或表单格式来上传文件呢?答案是肯定的。(下面马上揭晓)前端代码:

//方式5$(".btnfile5").click(function () {    $.AJAX({        url: "/Home/Savefile4",data: $("#file5")[0].files[0],// 告诉jquery不要去设置Content-Type请求头        success: function (responseText) {            alert(responseText);        }    });;       });            

后台代码:

public string Savefile4(){    //这里发现只能得到一个网络流,没有其他信息了。(比如,文件大小、文件格式、文件名等)    Request.SaveAs(Server.MapPath("~/App_Data/Savefile4.data") + "",false);    return "保存成功";}

细心的你发现没有了表单格式,我们除了可以上传文件流数据外,不能再告诉后台其他信息了(如文件格式)。到这里,我似乎明白了以前上传文件为什么非得要用个form包起来,原来这只是和后台约定的一个传输格式而已。其实我们单纯的用jq的AJAX传输文本数据的时候,最后也是组装成了form格式的数据,如:

 $.AJAX({    data: { "username": "张三" } 

在知道了上面的各种上传之后,我们是不是就满于现状了呢?no,很多时候我们需要传输大文件,一般服务器都会有一定的大小限制。某天,你发现了一个激情小电影想要分享个大家。无奈,高清文件太大传不了,怎么办?我们可以化整为零,一部分一部分的传嘛,也就是所谓的分片上传。前端代码:

//方式6 $(".btnfile6").click(function () {      var upload = function (file,skip) {         var formData = new FormData();//初始化一个FormData对象         var blockSize = 1000000;//每块的大小         var nextSize = Math.min((skip + 1) * blockSize,file.size);//读取到结束位置                      var fileData = file.slice(skip * blockSize,nextSize);//截取 部分文件 块         formData.append("file",fileData);//将 部分文件 塞入FormData         formData.append("filename",file.name);//保存文件名字         $.AJAX({             url: "/Home/Savefile6",// 告诉jquery不要去处理发送的数据             ContentType: false,// 告诉jquery不要去设置Content-Type请求头             success: function (responseText) {                 $(".result").HTML("已经上传了" + (skip + 1) + "块文件");                 if (file.size <= nextSize) {//如果上传完成,则跳出继续上传                     alert("上传完成");                     return;                 }                 upload(file,++skip);//递归调用             }         });     };
 var <a href="https://m.jb51.cc/tag/file/" target="_blank" >file</a> = $("#<a href="https://m.jb51.cc/tag/file/" target="_blank" >file</a>6")[0].<a href="https://m.jb51.cc/tag/file/" target="_blank" >file</a>s[0]; upload(<a href="https://m.jb51.cc/tag/file/" target="_blank" >file</a>,0);

});

后台代码:

public string Savefile6(){    //保存文件到根目录 App_Data + 获取文件名称和格式    var filePath = Server.MapPath("~/App_Data/") + Request.Form["filename"];    //创建一个追加(fileMode.Append)方式的文件流    using (fileStream fs = new fileStream(filePath,fileMode.Append,fileAccess.Write))    {        using (BinaryWriter bw = new BinaryWriter(fs))        {            //读取文件流            BinaryReader br = new BinaryReader(Request.files[0].inputStream);            //将文件留转成字节数组            byte[] bytes = br.ReadBytes((int)Request.files[0].inputStream.Length);            //将字节数组追加到文件            bw.Write(bytes);        }    }    return "保存成功";}

相对而言,代码量多了一点,复杂了一点。不过相对于网上的其他分片上传的代码应该要简单得多(因为这里没有考虑多文件块同时上传、断点续传。那样就需要在后台把文件块排序,然后上传完成按序合并,然后删除原来的临时文件。有兴趣的同学可以自己试试,稍候在分析上传插件webuploader的时候也会实现)。效果图:

input里面标记multiple,然后我们后台接收的也是一个数组Request.files

只能说H5真是强大啊,权限越来越大, *** 作越来越牛逼。前端代码(拖拽上传):