最近我维护的网站在审核时加了个上传下载的功能,能上传多个文件(文件很小、不超过3个、上传时可以多选、且要有上传进度),下载时有选择的下载。页面是用aspx做的,微软自带的只有单文件上传,于是乎想到flash。找了三个现成的,测试发现一个不兼容IE9,另两个都通过了,但发现有点山寨,flash是封装好的,一个上面有广告,一个是英文的,既是封装的,我也不知道里面到底干了什么,也没想去看As语言的语法。后来又找了个silverlight的,效果不错,但新的问题又有了,flash到时大多数电脑都装了的,但silverlight没装的人就多了去了,虽然给了下载的链接,但还是反映很差,时间又紧,无奈将功能裁减了点,上传时不显示实时进度,找了博客园上的cloudgamer写的仿163网盘的无刷新多文件上传系统,自己稍微改了改就用上去了。下载找的这篇文章,用的是aspx的UpdatePanel。上传的效果如下:
任务是完成了,但明显发现整合到我们项目中之后比较搓,我们项目用的Jquery,而这里是纯js(刚开始在IE9下还有Bug),我对js也不太熟悉,感觉这里还有些问题,于是花了点时间研究了里面的相关js语法,将基本的原理抽象出来,用Jquery写了个上传下载的例子,都是通过iframe实现的。
先说上传:上传本质是通过提交自带的file控件,然后对a标签做了点处理,首先a标签做成图片的,a标签里面是file控件,然后每次选择文件后将这个file控件隐藏,新建一个file控件,这样就实现了点击一个图标上传多个文件。下面给出最基本的实现,至于实时显示选择的文件、已经上传的文件以及其他取消的功能就看各人的发挥了。
下面贴出代码:Form窗体的代码
<form id="uploadForm" action="FileUpLoad.ashx">
<table>
<tr>
<td>
<a href="javascript:void(0);" class="files" id="idFile"></a>
</td>
<td>
<input id="idBtnupload" type="button" value="开始上传" />
</td>
</tr>
</table>
</form>
js的代码:
$(document).ready(function () {
//注册按钮的点击事件
$("#idBtnupload").click(btnUpLoad_onclick);
CreateFrame();
Init();
})
///创建iframe
function CreateFrame() {
var FrameName = "uploadFrame_" + Math.floor(Math.random() * 1000);
var oframe = $('<iframe name=' + FrameName + '>');
//修改样式是css,修改属性是attr
oframe.css("display", "none");
//在内部的前面加节点
$('body').prepend(oframe);
//设置form属性,关键是target要指向iframe
$("#uploadForm").attr("target", FrameName);
$("#uploadForm").attr("method", "post");
//注意ie的form没有enctype属性,要用encoding
$("#uploadForm").attr("encoding", "multipart/form-data");
}
///上传
function btnUpLoad_onclick() {
$("#uploadForm").submit();
}
///初始化时新建一个file类型文本框
function Init() {
var fileJquery = $("<input type='file'>").attr("name", "Test").attr("title", "Jquery");
//这是运用js的onchange属性赋值的(不知道用Jquery怎么实现,用Jquery绑定方法没能实现)
fileJquery[0].onchange = function () { return OperateAndNew(fileJquery[0]); };
fileJquery.appendTo("#idFile");
}
///每当添加一个附件时执行
function OperateAndNew(o) {
if (o.value != "") {
o.style.display = "none"
Init();
}
}
///上传完成后提示消息
function Finish(msg) {
alert(msg);
}
后台处理程序的代码:
using System.Web;
using System.IO;
namespace UpLoadAndDown1021.上传文件
{
/// <summary>
/// FileUpLoad 的摘要说明
/// </summary>
public class FileUpLoad : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
int iTotal = context.Request.Files.Count;
for (int i = 0; i < iTotal; i++)
{
HttpPostedFile file = context.Request.Files[i];
if (file.ContentLength > 0 || !string.IsNullOrEmpty(file.FileName))
{
//保存文件
file.SaveAs(System.Web.HttpContext.Current.Server.MapPath("./UpLoadFile/" + Path.GetFileName(file.FileName)));
}
}
context.Response.Write("<script>window.parent.Finish('上传文件成功!');</script>");
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
其次是下载:一开始用的a标签,直接点击下载,后来发现文本或者图片的话就不行,会直接在浏览器中打开;后来用Ajax异步调用时,但总有问题,我希望直接通知浏览器下载,而不是返回前台;于是也用iframe实现,本质上就是创建了一个iframe,然后将其指向下载的方法。
前台Form的代码:
<form id="idForm" action="">
下载文件:<input type="text" id="AnnexName" value="绝密资料共享.txt" />
<br />
文件全路径:<input type="text" style="width: 500px" id="FullName" value="D:\pfeEXE\UpLoadAndDown1021\Demo.DownLoad\TestFile\绝密资料.txt" />
<br />
<input type="button" id="btnDownLoad" name="Test" value="DownLoad" />
</form>
js代码:
$(document).ready(function () {
$("#btnDownLoad").click(btnDownLoad_onclick);
})
function CreateFrame() {
var AnnexName = $("#AnnexName").val();
var FullName = $("#FullName").val();
var FrameName = "uploadFrame_" + Math.floor(Math.random() * 1000);
var oframe = $('<iframe name=' + FrameName + '>');
//修改样式是css,修改属性是attr
oframe.css("display", "none");
oframe.attr("src", "DownLoad.aspx?opType=" + "DownLoadAnnex" + "&AnnexName=" + AnnexName + "&FullName=" + FullName);
//在内部的前面加节点
$('body').prepend(oframe);
}
function btnDownLoad_onclick() {
CreateFrame();
}
后台处理程序的代码:
using System;
using System.IO;
namespace UpLoadAndDown1021.Demo.DownLoad
{
public partial class DownLoad : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["opType"] == "DownLoadAnnex")
{
///完整路径名(包括文件名)
string fulleName = Request["FullName"];
///下载保存的文件名
string dispalyName = Request["AnnexName"];
DownLoadFile(fulleName, dispalyName);
}
}
/// <summary>
/// 下载文件
/// </summary>
/// <param name="FullName">待下载的全路径</param>
/// <param name="DisPalyName">显示的名称</param>
private void DownLoadFile(string FullName, string DisPalyName)
{
if (File.Exists(FullName))
{
FileInfo file = new FileInfo(FullName);
Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8"); //解决中文乱码
Response.AddHeader("Content-Disposition", "attachment; filename=" + Server.UrlEncode(DisPalyName)); //解决中文文件名乱码
Response.AddHeader("Content-length", file.Length.ToString());
Response.ContentType = "appliction/octet-stream";
Response.WriteFile(file.FullName);
Response.End();
}
else
{
//可以提示文件不存在或已丢失
}
}
}
}
至此完成,只是思想,实现的业务还很少,其他还有实时文件上传状态、进度等。项目源代码。欢迎阅读、讨论、转载,转载请保留原文地址。