网页下载文件实现方式及技巧

本次功能阐述

桌面应用程序将附件保存在数据库中(桌面应用直接与数据库交互的情况下,并且仅限制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下 点击保存或者另存为会使用迅雷,如果没有迅雷或者迅雷里没有设置浏览器监控,则浏览器自己下载。浏览器最简单实现的文件下载方式就阐述到这里。

原文地址:https://www.cnblogs.com/njcxwz/p/4882697.html