最近要做一个文件下载的功能, 简单得不能再简单.
因为实在API接口中返回的, 外面被框架包了一层再返回, 我懒得研究框架,直接找到别的类似的功能, 抄了一下.
由于没有源代码, 我就 只能用 反编译工具 ILSpy,简单把同事的dll反编译了一下,得到如下代码
private static void Download(string fileName, DataTable data) { HttpContext.Current.Response.ContentType = "application/octet-stream"; string str = HttpUtility.UrlEncode(Path.GetFileName(fileName)).Replace('+', ' '); HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + str); MemoryStream memoryStream = new MemoryStream(); HttpContext.Current.Response.Clear(); HttpContext.Current.Response.BinaryWrite(ExcelHelper.Export(data, "").GetBuffer()); HttpContext.Current.Response.End(); }
然后我大概看了一眼, 我就自己一边抄一边写,我写的是这样的
/// <summary> /// xml文件下载 /// </summary> /// <param name="fileName"></param> /// <param name="memoryStream"></param> private void Download(string fileName, MemoryStream memoryStream) { try { HttpContext.Current.Response.ContentType = "application/octet-stream"; string str = HttpUtility.UrlEncode(System.IO.Path.GetFileName(fileName)).Replace('+', ' '); HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + str); HttpContext.Current.Response.Clear(); // byte[] ubyte = System.Text.Encoding.UTF8.GetBytes(xmlStr); HttpContext.Current.Response.BinaryWrite(memoryStream.ToArray()); HttpContext.Current.Response.End(); } catch { } }
乍一看好像是没什么问题, 直到后来,我又要做一个导出的功能(别的项目模块)
我一下子也不想去找我自己之前的那个代码, 心想, 还是去 抄 同事的代码 (反编译dll 我觉得是件很有趣的事情)
我又反编译了一下同事的代码, 这次我仔细看了下,瞄到 一个
HttpContext.Current.Response.BinaryWrite(ExcelHelper.Export(data, "").GetBuffer());
这行代码里面 用的是 MemoryStream 的GetBuffer() 方法, 我对这个方法好像没什么印象,然后我又把我之前的代码找出来
我是这样写的 HttpContext.Current.Response.BinaryWrite(memoryStream.ToArray());
好家伙,我抄代码都能抄出不一样的东西来, 然后我就在 "垃圾堆" 里面搜索
memoryStream.ToArray() 和 memoryStream.GetBuffer() 的区别,然后巴拉巴拉一大堆,
大致意思就是说,
memoryStream.ToArray() 是返回 memoryStream 的 复制品, 返回速度慢
memoryStream.GetBuffer() 返回的是 memoryStream 的 内存引用,返回速度快,但是却把 很多没用到的 空数据做占用的地址空间也传递出来了
前半段我理解了, 后半段是个什么鬼?
于是我决定试一下, 用 Notepad++ 打开, 发现后面 有这个 NUL
这个 NUL 部分就是 占用的多于的空间地址的内容(导出的文件要消耗内存)
对于我导出的这个文件, 大小在2kb到 10几kb之间, 好像也区别不大.我还是用我的 memoryStream.ToArray() .
记下这个例子, 只是为了给自己提个醒, "温故而知新",不可 "狂妄自大".
</ArrayOfSysParamInfo>