网页下载文件实现方式及技巧
本次功能阐述
桌面应用程序将附件保存在数据库中(桌面应用直接与数据库交互的情况下,并且仅限制2M以下的文件),客户端浏览器根据轮询弹出信息,及时的下载附件
在下载的过程中遇到一些情况
首先ajax的方式无法直接下载文件,所以需要用form提交的方式来模拟ajax文件下载的方式
function downLoadFile(o) { if ($(o).html().indexOf("无附件") >= 0) { alert("无附件下载"); return; } var form = $("<form>"); form.attr('style', 'display:none'); form.attr('target', ''); form.attr('method', 'post'); form.attr('action', 'Ajax/basic/NoticeDialog.ashx'); var input1 = $('<input>'); input1.attr('type', 'hidden'); input1.attr('name', 'FID'); input1.attr('value', $(o).attr("fid")); $('body').append(form); form.append(input1); form.submit(); form.remove(); }
服务端 由于获取数据库的时候直接拿到了byte[]数组,所以可以直接向浏览器输出二进制文件了。
遇到的问题
ie中文乱码,火狐正常
所以需要判断客户端浏览器信息如果是IE浏览器就进行一次转码,火狐不转码。可以解决问题
ie浏览器下,点击下载的时候,弹出迅雷的情况下(迅雷里设置了监控浏览器)这时候下载的不是文件而是页面地址,所以迅雷里设置》高级设置》监控浏览器不选上,可以解决现在的问题,但是不是很友好(违背用户不可知原则,即用户不一定知道这一解决方法)。
if (context.Request.Form["FID"] != null) { string noticeId = context.Request.Form["FID"].ToString(); string sql = @"select FileName,Attachment,AttachmentType from dbo.Zj_Notice n where n.noticeid=" + noticeId + " "; DataTable dt = SqlHelper.GetDataTable(sql); string filename = dt.Rows[0]["FileName"].ToString(); byte[] attachment = dt.Rows[0]["Attachment"] as byte[]; //int arraysize = attachment.Length; //FileStream fs = new FileStream(context.Server.MapPath("~/files/") + filename, FileMode.OpenOrCreate, FileAccess.Write); //fs.Write(attachment, 0, arraysize); //fs.Close(); //context.Response.Redirect("~/files/" + filename); if (context.Request.UserAgent.ToLower().IndexOf("msie") > -1) { filename = HttpUtility.UrlEncode(dt.Rows[0]["FileName"].ToString(), Encoding.UTF8); } context.Response.AddHeader("Content-Disposition", "attachment;filename=" + filename); context.Response.ContentType = "application/octet-stream"; context.Response.Expires = -1; context.Response.BinaryWrite(attachment); context.Response.Flush(); context.Response.End(); return; }
所以进一步改进
if (context.Request.Form["FID"] != null) { string noticeId = context.Request.Form["FID"].ToString(); string sql = @"select FileName,Attachment,AttachmentType from dbo.Zj_Notice n where n.noticeid=" + noticeId + " "; DataTable dt = SqlHelper.GetDataTable(sql); string filename = dt.Rows[0]["FileName"].ToString(); byte[] attachment = dt.Rows[0]["Attachment"] as byte[]; int arraysize = attachment.Length; FileStream fs = new FileStream(context.Server.MapPath("~/files/") + filename, FileMode.OpenOrCreate, FileAccess.Write); fs.Write(attachment, 0, arraysize); fs.Close(); context.Response.Redirect("~/files/" + filename); //if (context.Request.UserAgent.ToLower().IndexOf("msie") > -1) //{ // filename = HttpUtility.UrlEncode(dt.Rows[0]["FileName"].ToString(), Encoding.UTF8); //} //context.Response.AddHeader("Content-Disposition", "attachment;filename=" + filename); //context.Response.ContentType = "application/octet-stream"; //context.Response.Expires = -1; //context.Response.BinaryWrite(attachment); //context.Response.Flush(); //context.Response.End(); return; }
每次向临时目录中生成文件,然后直接转向文件地址,火狐下依旧没什么问题,IE下 点击保存或者另存为会使用迅雷,如果没有迅雷或者迅雷里没有设置浏览器监控,则浏览器自己下载。浏览器最简单实现的文件下载方式就阐述到这里。