{
using System;
using System.Web;
using System.Net;
using System.IO;
using System.Text;
using System.Data;
using System.Data.SqlClient;
/*
* 1.支持断点续传
* 2.支持多线程下载
* 3.解决速度问题
* 4.文件播放解决拖动问题
* 5.解决服务器资源高占有问题
*/
/// <summary>
/// DownFile 的摘要说明。
/// </summary>
public class GetFile : System.Web.UI.Page
{
/*
* 支持断点续传
* 解决速度问题
* 支持大文件
*/
private string file ;
private string fileHead ;
private string sqlConnString ;
public string SqlConnString{
get{
if(sqlConnString==null)
sqlConnString = System.Configuration.ConfigurationSettings.AppSettings["SqlConnString"];
return sqlConnString;
}
}
private string headFilePath;
public string HeadFilePath{
get{
if(headFilePath==null)
headFilePath = System.Configuration.ConfigurationSettings.AppSettings["HeadFilePath"];
return headFilePath;
}
}
private void Login(){
// 从IChannal中捕获UserName 和 PassWord;
// <add key="LoginUrl" value="Http://192.168.2.89/yu.php?Require=name=111@111.com&pass=111111" />
string loginUrl = System.Configuration.ConfigurationSettings.AppSettings["LoginUrl"];
//"asdfffgsdf-=-sd09-593%@#42593049523-4"
//loginUrl += "name=111@111.com&pass=111111";
string userInfo = Request.Headers["UserInfo"];
if(userInfo == null){
// 用户没有登陆验证
// Response.Write("用户没有登陆!");
Response.StatusDescription = "用户没有登陆!";
ResponseEnd(407);
}
loginUrl += userInfo;
//利用 WebClient 取得远程登陆校验得结果
WebClient wc = new WebClient();
wc.Credentials = CredentialCache.DefaultCredentials;
try{
byte[] loginData = wc.DownloadData(loginUrl);
string loginResult = Encoding.Default.GetString(loginData);
//1 登陆成功 0 登陆失败 2 没有该用户名
if(System.Convert.ToInt32(loginResult) == 1)
return;
else if(System.Convert.ToInt32(loginResult) == 0){
//用户登陆校验失败
//Response.Write("用户登陆校验失败!");
Response.StatusDescription = "登陆失败!";
ResponseEnd(418);
}
else{ //(System.Convert.ToInt32(loginResult) == 2){
//Response.Write("不存在改用户名!");
Response.StatusDescription = "登陆失败!";
ResponseEnd(419);
}
}
catch(Exception){
//不能访问Url登陆,登陆结果异常,登陆失败
Response.StatusDescription = "不能访问Url登陆,登陆结果异常,登陆失败!";
ResponseEnd(420);
}
}
private void Permit(){
string cGuid = Request.QueryString["cguid"];
string fileName = Request.QueryString["f"];
if(cGuid == null || fileName == null){
Response.StatusDescription = "参数错误.";
ResponseEnd(412);
}
SqlConnection sqlConn = new SqlConnection(SqlConnString);
sqlConn.Open();
//校验下载次数
string sql ;
SqlCommand sqlCmd = new SqlCommand();
sqlCmd.CommandType = CommandType.Text;
sqlCmd.Connection = sqlConn;
sql = @"Select Retailers.RetailerUid From Retailers Inner Join LimitDownLoad on LimitDownLoad.RetailerId = Retailers.Id
Where LimitDownLoad.RetailerId = (Select RetailerId From LimitDownLoad Where ContentGuid=@ContentGuid)
Group By Retailers.LimitDown,Retailers.RetailerUid
Having Sum(LimitDownLoad.DownCount)<Retailers.LimitDown";
sqlCmd.CommandText = sql;
sqlCmd.Parameters.Add("@ContentGuid",SqlDbType.VarChar,36);
sqlCmd.Parameters["@ContentGuid"].Value = cGuid;
Object objDown = sqlCmd.ExecuteScalar();
if(objDown == null){
//校验失败,或没有经过下载预置(LimitDownLoad)
Response.StatusDescription = "校验失败,或没有经过下载预置(LimitDownLoad).";
sqlConn.Close();
ResponseEnd(402);
}
string rGuid = objDown.ToString();
//查找文件
sql = @"Select OutputFile+\'\\'+FileName As FileName From WaitPack Inner join LimitDownLoad On LimitDownLoad.ContentId=WaitPack.ContentId Where IsPacking=3 And LimitDownLoad.ContentGuid=@ContentGuid And FileName=@FileName";
sqlCmd.CommandText = sql;
sqlCmd.Parameters.Clear();
sqlCmd.Parameters.Add("@ContentGuid",SqlDbType.VarChar,36);
sqlCmd.Parameters["@ContentGuid"].Value = cGuid;
sqlCmd.Parameters.Add("@FileName",SqlDbType.VarChar,100);
sqlCmd.Parameters["@FileName"].Value = fileName;
Object objFile = sqlCmd.ExecuteScalar();
if(objFile == null){
//数据库中不存在改打包文件,即 该文件没有被打包
Response.StatusDescription = "数据库中不存在改打包文件.";
sqlConn.Close();
ResponseEnd(404);
}
//从数据库中取得文件的绝对物理路径
file = objFile.ToString();
//处理file中 \\192.168.2.3\\001.wmv => \\192.168.2.3\001.wmv 两者相等的
file = file.Replace(@"\\",@"\");
file = @"\"+file;
//--------end
fileHead = HeadFilePath+rGuid+@"\"+GetHeadFile(file);
fileHead = fileHead.Replace(@"\\",@"\");
//fileHead = @"\"+fileHead;
if(!File.Exists(file) || !File.Exists(fileHead)){
//文件或头文件不存在!
Response.StatusDescription = "文件或头文件不存在!";//或者是没有访问文件的权限
sqlConn.Close();
ResponseEnd(404);
}
//更新下载次数
/*
* 这部分 IChannal 那边下载完后处理
sql = "Update LimitDownLoad Set DownCount=DownCount+1 Where ContentGuid=@ContentGuid";
sqlCmd.CommandText = sql;
sqlCmd.Parameters.Clear();
sqlCmd.Parameters.Add("@ContentGuid",SqlDbType.VarChar,36);
sqlCmd.Parameters["@ContentGuid"].Value = cGuid;
sqlCmd.ExecuteNonQuery();
*/
sqlConn.Close();
}
private void ResponseEnd(int statusCode){
Response.StatusCode = statusCode;
Response.End();
}
private string GetHeadFile(string file){
string f1 = Path.GetFileNameWithoutExtension(file);
string f2 = Path.GetExtension(file);
return f1+"_h"+f2;
}
private string GetMime(string fileName){
string fileExtent = Path.GetExtension(fileName);
//int index = fileName.LastIndexOf(\'.\');
//fileName.Substring(index,fileName.Length-index-1);
string retMime;
switch(fileExtent){
case ".rm":
retMime = "application/vnd.rn-realmedia";
break;
case ".mp3":
retMime = "application/mp3";
break;
case ".asf":
retMime = "video/x-ms-asf";
break;
case ".avi":
retMime = "video/avi";
break;
case ".wav":
retMime = "audio/wav";
break;
case ".wmv":
retMime = "audio/wmv";
break;
case ".mpg":
retMime = "video/mpeg";
break;
case ".mpeg":
retMime = "video/mpeg";
break;
default:
retMime = "application/octet-stream";
break;
}
return retMime;
}
protected override void OnInit(EventArgs e)
{
//登陆校验
Login();
//过滤限制条件
Permit();
//file = @"C:\xx.wmv";
//fileHead = @"C:\xx_h.wmv";
//文件以共享方式打开
FileStream fs = new FileStream(file,FileMode.Open,FileAccess.Read,FileShare.Read);
Response.Clear();
Response.ContentType = GetMime(file);
//Range: bytes=449794- || bytes=449794-588888
FileStream fsHead = new FileStream(fileHead,FileMode.Open,FileAccess.Read,FileShare.Read);
byte[] buff = new byte[209152] ;
//文件长度,每个不同offset请求时,抛出给客户端的文件大小随之变化
long length = fs.Length-10240+fsHead.Length;
//得到客户端请求文件定位位置
string Range = Request.Headers["Range"];
//默认起始位置是文件开头,结尾位置是文件结尾
//去掉文件的头10K 大小!
long offset=0,endset = fs.Length-10240+fsHead.Length;
int len; //实际读的文件的字节数
Response.AppendHeader("Content-Disposition","attachment;filename=" +Path.GetFileName(file));
Response.Buffer = true;
Response.StatusCode = 200;
if(Range != null && Range != ""){
Response.StatusCode = 206;
int index = Range.IndexOf(\'=\');
Range = Range.Substring(index+1,Range.Length-index-1);
index = Range.IndexOf(\'-\');
//取得文件的开始和结尾的文件位置
offset = System.Convert.ToInt32(Range.Substring(0,index));
//if(index < Range.Length-1)
//endset = System.Convert.ToInt32(Range.Substring(index+1,Range.Length-index-1));
length = endset - offset ;
//文件定位
//fs.Seek(offset,SeekOrigin.Begin);
}
Response.AppendHeader("Content-Length",length.ToString());
//仅仅定位到头文件中!
//抛出头文件中的类容
if(offset < fsHead.Length) {
//头最大为10K左右 默认读取设置100k
fsHead.Seek(offset,SeekOrigin.Begin);
len = fsHead.Read(buff,0,102400);
Response.OutputStream.Write(buff,0,len);
Response.Flush();
fs.Seek(10240,SeekOrigin.Begin);
}
else{
//设置默认定位
fs.Seek(offset-fsHead.Length+10240,SeekOrigin.Begin);
}
//每次读取1M的类容
len = fs.Read(buff,0,209152);//104576 2M
while(len > 0 ) {
if (Response.IsClientConnected) {
Response.OutputStream.Write(buff,0,len);
Response.Flush();
len = fs.Read(buff,0,209152);//1048576
}
else {
len = 0;
}
}
fs.Close();
fsHead.Close();
Response.End();
}
}
}
Status Code
描述 |
Code |
用户没有登陆 |
407 |
密码错误,登陆失败 |
418 |
用户名不存在,登陆失败 |
419 |
登陆异常,登陆失败 |
420 |
Url参数错误 |
412 |
下载次数过期或没有经过下载预置 |
402 |
数据库中不存在该文件或改文件没有被打包 |
404 |
文件或头文件不存在 |
404 |
正常下载 |
200 |
下载文件类容 |
206 |