第一次写博客,写的不好还请多多指教
之前同事有一个需求,需要下载另一个服务器(A)上的文件到客户端,当时我给他做的一个例子是发送请求给A服务器,然后直接通知浏览器下载文件,但是需求邮编,要求支持多文件,那就有点麻烦了,主要局限在HTTP是无状态的,当第一个文件下载完成了,后面的文件就不会在下载到客户端了,因为一次完整的请求已经结束了,由于同事说第二天要结果,不管质量,所以暂时写了这个例子,看代码,主要的思路是将A服务器上文件下载到我的web服务器上,然后在打包,之后下载到客户端,程序中使用了SharpZipLib.dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.Threading;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<string> pathlist = new List<string>();//模拟待下载的多个文件
pathlist.Add(@"http://127.0.0.1:6528/services/file/Ford.mp4");
pathlist.Add(@"http://127.0.0.1:6528/services/file/Ford.mp4");
pathlist.Add(@"http://127.0.0.1:6528/services/file/Ford.mp4");
pathlist.Add(@"http://127.0.0.1:6528/services/file/Ford.mp4");
pathlist.Add(@"http://127.0.0.1:6528/services/file/Ford.mp4");
List<string> fileName = new List<string>();
string id = Guid.NewGuid().ToString();
Directory.CreateDirectory(Server.MapPath("~/file/" + id + "/"));//生成保存文件的路径
for (int i = 0; i < pathlist.Count; i++)
{
// 设置参数
HttpWebRequest request = WebRequest.Create(pathlist[i]) as HttpWebRequest;
//发送请求并获取相应回应数据
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
//直到request.GetResponse()程序才开始向目标网页发送Post请求
Stream responseStream = response.GetResponseStream();//得到响应流
//创建本地文件写入流
string savepath = Server.MapPath("~/file/" + id + "/") + i + pathlist[i].Substring(pathlist[i].LastIndexOf("/") + 1);//将文件保存到指定WEB服务器指定路径下
Stream stream = new FileStream(savepath, FileMode.OpenOrCreate);//创建保存在web服务器上的路径
byte[] bArr = new byte[1024];
int size = responseStream.Read(bArr, 0, (int)bArr.Length);
while (size > 0)
{
stream.Write(bArr, 0, size);
size = responseStream.Read(bArr, 0, (int)bArr.Length);
}
stream.Close();
responseStream.Close();
}
string[] FileProperties = new string[2];
FileProperties[0] = Server.MapPath("~/file/" + id + "/");//待压缩文件目录
FileProperties[1] = Server.MapPath("~/fielRar/"+id+".zip"); //压缩后的目标文件
ZipFloClass Zc = new ZipFloClass();
Zc.ZipFile(FileProperties[0], FileProperties[1]);
downStream(Server.MapPath("~/fielRar/" + id + ".zip"), Server.MapPath("~/file/" + id + "/"));//下载压缩后的文件
}
/// <summary>
/// //流方式下载
/// </summary>
/// <param name="serverPath">压缩文件物理地址</param>
/// <param name="path">源文件目录物理地址</param>
protected void downStream(string serverPath,string path)
{
string fileName = DateTime.Now.ToString("yyyymmddhhssmm")+".zip";//客户端保存的文件名
string filePath = serverPath;//压缩文件物理路径
//以字符流的形式下载文件
FileStream fs = new FileStream(filePath, FileMode.Open);
byte[] bytes = new byte[(int)fs.Length];
fs.Read(bytes, 0, bytes.Length);
fs.Close();
Response.ContentType = "application/octet-stream";
//通知浏览器下载文件而不是打开
Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
DirectoryInfo di = new DirectoryInfo(path);
di.Delete(true);//删除源文件目录
File.Delete(serverPath);//删除压缩后的文件
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();
}
//WriteFile分块下载
protected void WriteFile1(string serverPath, string path)
{
string fileName = DateTime.Now.ToString("yyyymmddhhssmm") + ".zip";//客户端保存的文件名
string filePath = serverPath;//路径
System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
if (fileInfo.Exists == true)
{
const long ChunkSize = 102400;//100K 每次读取文件,只读取100K,这样可以缓解服务器的压力
byte[] buffer = new byte[ChunkSize];
Response.Clear();
System.IO.FileStream iStream = System.IO.File.OpenRead(filePath);
long dataLengthToRead = iStream.Length;//获取下载的文件总大小
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName));
while (dataLengthToRead > 0 && Response.IsClientConnected)
{
int lengthRead = iStream.Read(buffer, 0, Convert.ToInt32(ChunkSize));//读取的大小
Response.OutputStream.Write(buffer, 0, lengthRead);
Response.Flush();
dataLengthToRead = dataLengthToRead - lengthRead;
}
DirectoryInfo di = new DirectoryInfo(path);
di.Delete(true);//删除源文件目录
File.Delete(serverPath);//删除压缩后的文件
Response.Close();
}
}
//WriteFile实现下载
protected void WriteFile2(string serverPath, string path)
{
string fileName = DateTime.Now.ToString("yyyymmddhhssmm") + ".zip";//客户端保存的文件名
string filePath = serverPath;//路径
FileInfo fileInfo = new FileInfo(filePath);
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.AddHeader("Content-Transfer-Encoding", "binary");
Response.ContentType = "application/octet-stream";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312");
DirectoryInfo di = new DirectoryInfo(path);
di.Delete(true);//删除源文件目录
File.Delete(serverPath);//删除压缩后的文件
Response.WriteFile(fileInfo.FullName);
Response.Flush();
Response.End();
}
打包还需要另外建立两个类UnZipFloClass.cs和ZipFloClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
/// <summary>
///UnZipFloClass 的摘要说明
/// </summary>
public class UnZipFloClass
{
public string unZipFile(string TargetFile, string fileDir)
{
string rootFile = " ";
try
{
//读取压缩文件(zip文件),准备解压缩
ZipInputStream s = new ZipInputStream(File.OpenRead(TargetFile.Trim()));
ZipEntry theEntry;
string path = fileDir;
//解压出来的文件保存的路径
string rootDir = " ";
//根目录下的第一个子文件夹的名称
while ((theEntry = s.GetNextEntry()) != null)
{
rootDir = Path.GetDirectoryName(theEntry.Name);
//得到根目录下的第一级子文件夹的名称
if (rootDir.IndexOf("\\") >= 0)
{
rootDir = rootDir.Substring(0, rootDir.IndexOf("\\") + 1);
}
string dir = Path.GetDirectoryName(theEntry.Name);
//根目录下的第一级子文件夹的下的文件夹的名称
string fileName = Path.GetFileName(theEntry.Name);
//根目录下的文件名称
if (dir != " ")
//创建根目录下的子文件夹,不限制级别
{
if (!Directory.Exists(fileDir + "\\" + dir))
{
path = fileDir + "\\" + dir;
//在指定的路径创建文件夹
Directory.CreateDirectory(path);
}
}
else if (dir == " " && fileName != "")
//根目录下的文件
{
path = fileDir;
rootFile = fileName;
}
else if (dir != " " && fileName != "")
//根目录下的第一级子文件夹下的文件
{
if (dir.IndexOf("\\") > 0)
//指定文件保存的路径
{
path = fileDir + "\\" + dir;
}
}
if (dir == rootDir)
//判断是不是需要保存在根目录下的文件
{
path = fileDir + "\\" + rootDir;
}
//以下为解压缩zip文件的基本步骤
//基本思路就是遍历压缩文件里的所有文件,创建一个相同的文件。
if (fileName != String.Empty)
{
FileStream streamWriter = File.Create(path + "\\" + fileName);
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
streamWriter.Close();
}
}
s.Close();
return rootFile;
}
catch (Exception ex)
{
return "1; " + ex.Message;
}
}
}
--------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
/// <summary>
///ZipFloClass 的摘要说明
/// </summary>
public class ZipFloClass
{
public void ZipFile(string strFile, string strZip)
{
if (strFile[strFile.Length - 1] != Path.DirectorySeparatorChar)
strFile += Path.DirectorySeparatorChar;
ZipOutputStream s = new ZipOutputStream(File.Create(strZip));
s.SetLevel(6); // 0 - store only to 9 - means best compression
zip(strFile, s, strFile);
s.Finish();
s.Close();
}
private void zip(string strFile, ZipOutputStream s, string staticFile)
{
if (strFile[strFile.Length - 1] != Path.DirectorySeparatorChar) strFile += Path.DirectorySeparatorChar;
Crc32 crc = new Crc32();
string[] filenames = Directory.GetFileSystemEntries(strFile);
foreach (string file in filenames)
{
if (Directory.Exists(file))
{
zip(file, s, staticFile);
}
else // 否则直接压缩文件
{
//打开压缩文件
FileStream fs = File.OpenRead(file);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
string tempfile = file.Substring(staticFile.LastIndexOf("\\") + 1);
ZipEntry entry = new ZipEntry(tempfile);
entry.DateTime = DateTime.Now;
entry.Size = fs.Length;
fs.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
s.PutNextEntry(entry);
s.Write(buffer, 0, buffer.Length);
}
}
}
}