ASP.NET大文件断点上传

时间:2022-08-29 08:32:59

前端代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<script language="javascript">
//全选
function CheckAll(e, itemname) {
var aa = document.getElementsByName(itemname);
if (aa == undefined) return;
for (var i = 0; i < aa.length; i++) aa[i].checked = e.checked;
}
</script>
<script language="javascript">
//判断复选框是否选中
function delss() {
var checkArray = document.getElementsByName("Item");
var checkNum = 0;
for (var i = 0; i < checkArray.length; i++) {
if (checkArray[i].checked) { checkNum++; }
}
if (checkNum == 0) {
alert('对不起,您还没有选择!');
return false;
}
else {
if (confirm("您确定要删除吗?")) {
return true;
} else {
return false;
}
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:Timer ID="Timer1" runat="server" Interval="1000" OnTick="Timer1_Tick">
</asp:Timer>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" EventName="tick" />
</Triggers>
</asp:UpdatePanel>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="上传文件" OnClick="Button1_Click" />
<table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#cccccc">
<tr class="spgl_bg">
<td width="6%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">
<input name="chkall" value="1" type="checkbox" onclick="CheckAll(this,'Item')" class="qx" />全选
</td>
<td width="6%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">
编号
</td>
<td width="16%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">
名称
</td>
<td width="52%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">
上传文件地址
</td>
<td width="8%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">
已上传
</td>
<td width="12%" height="22" align="center" valign="middle" bgcolor="#FFFFFF">
操作
</td>
</tr>
<asp:Repeater ID="rptList" runat="server">
<ItemTemplate>
<tr>
<td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>">
<input name="Item" type="checkbox" value='<%# Eval("fid")%>' />
</td>
<td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>">
<%# Container.ItemIndex + 1 %>
</td>
<td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>"
class="gml">
<%# Eval("FileNameLocal")%>
</td>
<td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>"
class="gml">
<%# Eval("FilePathLocal")%>
</td>
<td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>"
class="gml">
<%# Eval("PostedPercent")%>
</td>
<td align="center" valign="middle" bgcolor="<%#(Container.ItemIndex%2==0)?"#FFFFFF":"#f2f2f2"%>">
<asp:LinkButton ID="lbTop" runat="server" Text='续传' CommandArgument='<%# Eval("fid") %>'
OnCommand="lbTop_Click"></asp:LinkButton>|
<asp:LinkButton ID="lbClose" Visible="false" runat="server" Text='停止' CommandArgument='<%# Eval("fid") %>'
OnCommand="lbClose_Click"></asp:LinkButton>
<asp:LinkButton ID="lbDel" runat="server" Text="删除" OnCommand="lbDel_Click" CommandArgument='<%# Eval("fid") %>'
OnClientClick="javascript:return confirm('您确定要删除吗?');"></asp:LinkButton>
</td>
<asp:HiddenField ID="hidOK" runat="server" Value='<%# Eval("Isok") %>' />
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
<asp:Button ID="btnAllDelete" runat="server" Text="批量删除" class="plsc" CommandName="delete"
OnClientClick="return delss()" OnCommand="btnAllDelete_Command" />
</form>
</body>
</html>

后端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Web.demoSql.db;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Threading;

namespace Web
{
public partial class Index : System.Web.UI.Page
{
#region
public long m_FileSize; //文件总大小。
long m_RangePos; //文件块起始位置
public long RangePos
{
set { this.m_RangePos = value; }
}
//文件读写锁,防止多个用户同时上传相同文件时,出现创建文件的错误
static ReaderWriterLock m_writeLock = new ReaderWriterLock();
#endregion
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GetList();
}
}

/// <summary>
/// 上传事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button1_Click(object sender, EventArgs e)
{
#region 获取上传文件的信息
string md5Fisrt = GenerateCheckCode10();
string uidFisrt = "0";
string fileLengthFisrt = FileUpload1.PostedFile.ContentLength.ToString();
string fileSizeFisrt = Math.Round(Convert.ToDouble(FileUpload1.PostedFile.ContentLength) / Convert.ToDouble(1024 * 1024), 2).ToString() + "MB";
string pathLocalFisrt = FileUpload1.PostedFile.FileName;
#endregion

string FileType = FileUpload1.FileName.Substring(FileUpload1.FileName.LastIndexOf(".") + 1);
if (FileUpload1.FileName == "" || Request.Files.Count < 0)
{
string msg = "请选择文件!";
Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");
}
else if (FileType.ToLower() != "rar")
{
string msg = "文件格式不正确!";
Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");

}
else
{
#region 向数据库插入上传文件信息
HttpUploaderDB db = new HttpUploaderDB();
xdb_files inf = new xdb_files();
inf.FileNameLocal = Path.GetFileName(pathLocalFisrt);
inf.FilePathLocal = pathLocalFisrt;
inf.FileNameRemote = md5Fisrt + Path.GetExtension(pathLocalFisrt).ToLower();

//数据库存在相同文件
if (db.GetFileInfByMd5(md5Fisrt, ref inf))
{
inf.FileNameLocal = Path.GetFileName(pathLocalFisrt);
inf.FilePathLocal = pathLocalFisrt;
inf.uid = int.Parse(uidFisrt);//将当前文件UID设置为当前用户UID
inf.IsDeleted = false;
inf.fid = db.Add(ref inf);
}//数据库不存在相同文件
else
{
HttpUploaderCfg cfg = new HttpUploaderCfg();
cfg.CreateUploadPath();

inf.uid = int.Parse(uidFisrt);//将当前文件UID设置为当前用户UID
inf.FileSize = fileSizeFisrt;
inf.FileMD5 = md5Fisrt;
inf.FileLength = Convert.ToInt32(fileLengthFisrt);
inf.FilePathRemote = Path.Combine(cfg.GetUploadPath(), inf.FileNameRemote);
inf.FilePathRelative = Path.Combine(cfg.GetRelatPath(), inf.FileNameRemote);
inf.fid = db.Add(ref inf);
GetList();
}
#endregion

#region 更新上传进度

int num = 0;
string struid = uidFisrt;
string strfid = inf.fid.ToString();
string strFileSize = fileLengthFisrt;
string strRangePos = num.ToString();

if (strFileSize.Length > 0
&& struid.Length > 0
&& strfid.Length > 0
&& md5Fisrt.Length > 0
&& strRangePos.Length > 0
&& Request.Files.Count > 0)
{
long fileSize = Convert.ToInt64(strFileSize);
long rangePos = Convert.ToInt64(strRangePos);
int uid = Convert.ToInt32(struid);
int fid = Convert.ToInt32(strfid);

//临时文件大小
HttpPostedFile file = Request.Files.Get(0);
long rangeSize = 131072;
long rangeSiHH = 131072;
xdb_files infModel = new xdb_files();

for (long i = 0; i <= Convert.ToInt32(file.InputStream.Length); )
{
if (db.GetFileInfByFid(fid, ref infModel))
{
//已上传大小 = 文件块索引 + 临时文件块大小
//long postedLength = rangePos + rangeSize;
long postedLength = i + rangeSize;
long nownum = i;
if (file.InputStream.Length < postedLength)
{
postedLength = file.InputStream.Length - nownum;
rangeSiHH = file.InputStream.Length - nownum;
}
//上传百分比 = 已上传大小 / 文件总大小
double per = ((double)postedLength / (double)fileSize) * 100;
decimal perd = Math.Round((decimal)per, 2);
string postedPercent = perd.ToString() + "%";

//保存文件块数据
FileResumer res = new FileResumer();
res.m_FileSize = fileSize;//根据客户端文件大小在服务端创建文件
res.RangePos = rangePos;

#region
m_writeLock.AcquireWriterLock(1000);
//文件不存在则创建
if (!File.Exists(infModel.FilePathRemote))
{
FileStream fs = File.OpenWrite(infModel.FilePathRemote);
BinaryWriter w = new BinaryWriter(fs);
for (long ii = 0; ii < infModel.FileLength; ++ii)
{
w.Write((byte)0);
}
w.Close();
fs.Close();
}
m_writeLock.ReleaseWriterLock();

//上传的文件大小不为空
if (rangeSiHH > 0)
{
//文件已存在,写入数据
//可能会有多个线程同时写文件。
FileStream fs = new FileStream(infModel.FilePathRemote, FileMode.Open, FileAccess.Write, FileShare.Write);
fs.Seek(i, SeekOrigin.Begin);
byte[] ByteArray = new byte[rangeSiHH];
file.InputStream.Read(ByteArray, 0, (int)rangeSiHH);
fs.Write(ByteArray, 0, (int)rangeSiHH);
fs.Flush();
fs.Close();
}
#endregion

//更新文件进度
db.UpdateProgress(uid, fid, rangePos, postedLength, postedPercent);
i += rangeSize;
}
}
}
#endregion

#region 上传完成
db.UploadComplete(md5Fisrt);
#endregion

GetList();
}

}

/// <summary>
/// 续传
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void lbTop_Click(object sender, CommandEventArgs e)
{
int id = Convert.ToInt32(e.CommandArgument);
HttpUploaderDB db = new HttpUploaderDB();
#region 设置按钮状态
foreach (RepeaterItem grv in rptList.Items)
{
LinkButton lb1 = (LinkButton)rptList.Items[grv.ItemIndex].FindControl("lbTop");//续传
LinkButton lb2 = (LinkButton)rptList.Items[grv.ItemIndex].FindControl("lbClose");//停止

lb1.Enabled = false;
lb2.Enabled = false;
}
LinkButton t = (LinkButton)sender;
RepeaterItem ri = (RepeaterItem)t.NamingContainer;
LinkButton itemid = ((LinkButton)ri.FindControl("lbClose"));
itemid.Enabled = true;
#endregion

#region 获取上传文件的信息
string md5Fisrt = GenerateCheckCode10();
string uidFisrt = "0";
string fileLengthFisrt = FileUpload1.PostedFile.ContentLength.ToString();
string fileSizeFisrt = Math.Round(Convert.ToDouble(FileUpload1.PostedFile.ContentLength) / Convert.ToDouble(1024 * 1024), 2).ToString() + "MB";
string pathLocalFisrt = FileUpload1.PostedFile.FileName;

xdb_files model = db.GetModelByID(id);
md5Fisrt = model.FileMD5;
string FileType = FileUpload1.FileName.Substring(FileUpload1.FileName.LastIndexOf(".") + 1);

if (FileUpload1.FileName == "" || Request.Files.Count < 0)
{
string msg = "请选择文件!";
Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");
}
else if (pathLocalFisrt != model.FilePathLocal || fileLengthFisrt != Convert.ToString(model.FileLength))
{
string msg = "第一次上传文件与本次上传文件不符合!";
Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");
}
else if (FileType.ToLower() != "rar")
{
string msg = "文件格式不正确!";
Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");
}
else
{
#region 更新上传进度

int num = 0;
string struid = uidFisrt;
string strfid = id.ToString();
string strFileSize = fileLengthFisrt;
string strRangePos = num.ToString();

if (strFileSize.Length > 0
&& struid.Length > 0
&& strfid.Length > 0
&& md5Fisrt.Length > 0
&& strRangePos.Length > 0
&& Request.Files.Count > 0)
{
long fileSize = Convert.ToInt64(strFileSize);
long rangePos = Convert.ToInt64(strRangePos);
int uid = Convert.ToInt32(struid);
int fid = Convert.ToInt32(strfid);

//临时文件大小
HttpPostedFile file = Request.Files.Get(0);
long rangeSize = 131072;
long rangeSiHH = 131072;
xdb_files infModel = new xdb_files();

for (long i = model.FilePos; i <= Convert.ToInt32(file.InputStream.Length); )
{
if (db.GetFileInfByFid(fid, ref infModel))
{
//已上传大小 = 文件块索引 + 临时文件块大小
//long postedLength = rangePos + rangeSize;
long postedLength = i + rangeSize;
long nownum = i;
if (file.InputStream.Length < postedLength)
{
postedLength = file.InputStream.Length - nownum;
rangeSiHH = file.InputStream.Length - nownum;
}
//上传百分比 = 已上传大小 / 文件总大小
double per = ((double)postedLength / (double)fileSize) * 100;
decimal perd = Math.Round((decimal)per, 2);
string postedPercent = perd.ToString() + "%";

//保存文件块数据
FileResumer res = new FileResumer();
res.m_FileSize = fileSize;//根据客户端文件大小在服务端创建文件
res.RangePos = rangePos;

#region
m_writeLock.AcquireWriterLock(1000);
//文件不存在则创建
if (!File.Exists(infModel.FilePathRemote))
{
FileStream fs = File.OpenWrite(infModel.FilePathRemote);
BinaryWriter w = new BinaryWriter(fs);
for (long ii = 0; ii < infModel.FileLength; ++ii)
{
w.Write((byte)0);
}
w.Close();
fs.Close();
}
m_writeLock.ReleaseWriterLock();

//上传的文件大小不为空
if (rangeSiHH > 0)
{
//文件已存在,写入数据
//可能会有多个线程同时写文件。
FileStream fs = new FileStream(infModel.FilePathRemote, FileMode.Open, FileAccess.Write, FileShare.Write);
fs.Seek(i, SeekOrigin.Begin);
byte[] ByteArray = new byte[rangeSiHH];
file.InputStream.Read(ByteArray, 0, (int)rangeSiHH);
fs.Write(ByteArray, 0, (int)rangeSiHH);
fs.Flush();
fs.Close();
}
#endregion

//更新文件进度
db.UpdateProgress(uid, fid, rangePos, postedLength, postedPercent);
i += rangeSize;
}
}
}
#endregion

#region 上传完成
db.UploadComplete(md5Fisrt);
#endregion
GetList();
}
#endregion
EnabledStop();
}

/// <summary>
/// 停止
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void lbClose_Click(object sender, CommandEventArgs e)
{
EnabledStop();
}

/// <summary>
/// 删除
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void lbDel_Click(object sender, CommandEventArgs e)
{
int id = Convert.ToInt32(e.CommandArgument);
HttpUploaderDB db = new HttpUploaderDB();
db.Del(id);

GetList();
}

/// <summary>
/// 批量删除事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnAllDelete_Command(object sender, CommandEventArgs e)
{
HttpUploaderDB db = new HttpUploaderDB();
string ids = Request.Form["Item"];
switch (e.CommandName)
{
case "delete":
BakDelete(ids);
break;
}
GetList();
}
/// <summary>
/// 批量删除方法
/// </summary>
/// <param name="ids"></param>
private void BakDelete(string ids)
{
HttpUploaderDB db = new HttpUploaderDB();
string strapp = ids;
string[] strtemp = strapp.Split(',');
foreach (string strs in strtemp)
{
db.Del(Convert.ToInt32(strs.ToString()));
}
}

/// <summary>
/// 获取数据列表
/// </summary>
public void GetList()
{
HttpUploaderDB db = new HttpUploaderDB();
rptList.DataSource = db.GetList();
rptList.DataBind();
EnabledStop();
}

/// <summary>
/// 禁用所有停止控件,启用所有续传控件
/// </summary>
public void EnabledStop()
{
foreach (RepeaterItem grv in rptList.Items)
{
LinkButton lb1 = (LinkButton)rptList.Items[grv.ItemIndex].FindControl("lbTop");//续传
LinkButton lb2 = (LinkButton)rptList.Items[grv.ItemIndex].FindControl("lbClose");//停止
HiddenField hidk = (HiddenField)rptList.Items[grv.ItemIndex].FindControl("hidOK");//上传是否完成
if (hidk.Value.ToLower() == "true")
{
lb1.Enabled = false;
lb2.Enabled = false;
}
else
{
lb1.Enabled = true;
lb2.Enabled = false;
}
}
}

/// <summary>
/// 刷新时间
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Timer1_Tick(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToString();
//GetList();
}

private string GenerateCheckCode10()
{
int number;
char code;
string checkCode = String.Empty;

System.Random random = new Random();

for (int i = 0; i < 10; i++)
{
number = random.Next();

if (number % 2 == 0)
code = (char)('0' + (char)(number % 10));
else
code = (char)('A' + (char)(number % 26));

checkCode += code.ToString();
}
return checkCode;
}
}
}