netmvc上传大文件
A. 求C#.NET上传大文件的三种解决方案
HTML部分
<%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx.cs"Inherits="up6.index"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=gb2312"/>
<title>up6-多标签演示页面</title>
<linkhref="js/up6.css"type="text/css"rel="Stylesheet"charset="gb2312"/>
<scripttype="text/javascript"src="js/jquery-1.4.min.js"></script>
<scripttype="text/javascript"src="js/json2.min.js"charset="utf-8"></script>
<scripttype="text/javascript"src="js/up6.config.js"charset="utf-8"></script>
<scripttype="text/javascript"src="js/up6.app.js"charset="utf-8"></script>
<scripttype="text/javascript"src="js/up6.edge.js"charset="utf-8"></script>
<scripttype="text/javascript"src="js/up6.file.js"charset="utf-8"></script>
<scripttype="text/javascript"src="js/up6.folder.js"charset="utf-8"></script>
<scripttype="text/javascript"src="js/up6.js"charset="utf-8"></script>
<scriptlanguage="javascript"type="text/javascript">
varcbMgr =newHttpUploaderMgr();
cbMgr.event.md5Complete =function(obj, md5) {/*alert(md5);*/};
cbMgr.event.fileComplete =function(obj) {/*alert(obj.fileSvr.pathSvr);*/};
cbMgr.event.queueComplete =function() { $(document.body).append("队列完成<br/>"); }
cbMgr.event.addFdError =function(jv) { alert("本地路径不存在:"+ jv.path); };
cbMgr.event.scanComplete =function(obj) {/*alert(obj.folderSvr.pathLoc);*/};
cbMgr.Config["Cookie"] ='ASP.NET_SessionId=<%=Session.SessionID%>';
cbMgr.Config.Fields["uid"] = 0;
$(function()
{
cbMgr.load_to("FilePanel");
//上传指定文件
$("#btnUpF").click(function() {
varpath = $("#filePath").val();
cbMgr.app.addFile({ pathLoc: path });
});
//上传指定目录
$("#btnUpFd").click(function() {
varpath = $("#folderPath").val();
cbMgr.app.addFolder({ pathLoc: path });
});
});
</script>
</head>
<body>
<p>up6多标签上传演示页面</p>
<p><ahref="db/clear.aspx"target="_blank">清空数据库</a></p>
<p><ahref="filemgr/index.aspx"target="_blank">文件管理器演示</a></p>
<p><ahref="index2.aspx"target="_blank">单面板演示</a></p>
<p><ahref="down2/index.htm"target="_blank">打开下载页面</a></p>
<p><ahref="index-single.htm"target="_blank">单文件上传演示</a></p>
<p>
文件路径:<inputid="filePath"type="text"size="50"value="D:\360safe-inst.exe"/>
<inputid="btnUpF"type="button"value="上传本地文件"/>
</p>
<p>
目录路径:<inputid="folderPath"type="text"size="50"value="C:\Users\Administrator\Desktop\test"/>
<inputid="btnUpFd"type="button"value="上传本地目录"/>
</p>
<divid="FilePanel"></div>
<divid="msg"></div>
</body>
</html>
代码部分
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace WebPortal
{
/// <summary>
/// UpLoad的摘要说明。
///实现多文件上传
/// </summary>
publicclass Upload: System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button UploadButton;
protected System.Web.UI.WebControls.Label strStatus;
privatevoid Page_Load(object sender, System.EventArgs e)
{
///在此处放置用户代码以初始化页面
if(this.IsPostBack)this.SaveImages();
}
private Boolean SaveImages()
{
///'遍历File表单元素
HttpFileCollection files= HttpContext.Current.Request.Files;
/// '状态信息
System.Text.StringBuilder strMsg=new System.Text.StringBuilder();
strMsg.Append("上传的文件分别是:<hr color=red>");
try
{
for(int iFile= 0; iFile< files.Count; iFile++)
{
///'检查文件扩展名字
HttpPostedFile postedFile= files[iFile];
string fileName, fileExtension;
fileName= System.IO.Path.GetFileName(postedFile.FileName);
if(fileName!="")
{
fileExtension= System.IO.Path.GetExtension(fileName);
strMsg.Append("上传的文件类型:"+ postedFile.ContentType.ToString()+"<br>");
strMsg.Append("客户端文件地址:"+ postedFile.FileName+"<br>");
strMsg.Append("上传文件的文件名:"+ fileName+"<br>");
strMsg.Append("上传文件的扩展名:"+ fileExtension+"<br><hr>");
///'可根据扩展名字的不同保存到不同的文件夹
///注意:可能要修改你的文件夹的匿名写入权限。
postedFile.SaveAs(System.Web.HttpContext.Current.Request.MapPath("images/")+ fileName);
}
}
strStatus.Text= strMsg.ToString();
returntrue;
}
catch(System.Exception Ex)
{
strStatus.Text= Ex.Message;
returnfalse;
}
}
#region Web窗体设计器生成的代码
overrideprotectedvoid OnInit(EventArgs e)
{
//
// CODEGEN:该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
///设计器支持所需的方法 - 不要使用代码编辑器修改
///此方法的内容。
/// </summary>
privatevoid InitializeComponent()
{
this.ID="Upload";
this.Load+=new System.EventHandler(this.Page_Load);
}
#endregion
}
}
选择文件夹
后端代码逻辑大部分是相同的
B. Asp.Net MVC3 上传文件问题
可以考虑一下以下代码:首先创建:一 创建表单
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })){ <input type="file" name="file" /> <input type="submit" value="OK" />}
二 创建controlle
public class HomeController : Controller{ // This action renders the form public ActionResult Index() { return View(); } // This action handles the form POST and the upload [HttpPost] public ActionResult Index(HttpPostedFileBase file) { // Verify that the user selected a file if (file != null && file.ContentLength > 0) { // extract only the fielname var fileName = Path.GetFileName(file.FileName); // store the file inside ~/App_Data/uploads folder var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName); file.SaveAs(path); } // redirect back to the index action to show the form once again return RedirectToAction("Index"); }}
C. asp.net mvc 如何不用form上传文件
html与服务器交互本质就是form提交,不用form服务器不可能得到数据。
$.ajax()里面构造form表单然后把file标签append到form中post提交。注意上传form的属性类型要加multi....data(忘记名字了类似这个)
D. asp.net用多线程上传大文件(500MB~2G)
众所周知,如果需要向WEB服务器上传文件,一般选用下列2种方式。
1. 使用HTTP PUT指令
2. 模拟页面的form提交
第一种需要配置服务器,略过。
第二种需要使用WinInet根据HTTP协议,拼除POST BODY后提交。
对于第二种,在ASP.Net里面特麻烦。
1. 需要模拟页面的VIEWSTATE,模拟不成功就不行
2. ASP.Net对每个请求有最大长度限制,这个值默认为4MB,但可以在web.config中修改
3. 文件在上传过程中并没有直接写入磁盘,而是先放入了内存,等到全部上传结束再写入磁盘。所以如果传输超大的文件对服务器性能影响很大
本文的做法是:
客户端不需要模拟form,将大文件分成等大的小块(如64K),使用多线程将这些小块上传到服务器后,服务器再拼合起来。
---------------------------------------------------------
流程:
1. 客户端:需要向服务器上传一个文件,首先调用服务器的某一个页面(如BeginUpload.aspx),通知此文件的大小(bytes)
2.服务器:服务器收到此请求,首先验证客户端权限,然后在自定义的文件夹中按照请求中提供的大小创建一个空文件,并返回一个唯一标示码到客户端。
3.客户端:收到服务器返回成功后,记录下此次上传的唯一标识码。
4.客户端:将需要上传的这个文件分成大小相等的文件块(如64K)。(这个过程只是一个逻辑上的过程,实际的做法并不需要分块,可以直接使用内存映射文件或者将文件直接读入到虚拟内存以加快速度)
5.客户端:开启一个领导者-跟随者线程池。领导者线程负责要上传文件块的调度,而跟随者线程负责自己分配到的文件块上传。
6.客户端,跟随者线程:读取自己分配到的文件块,向服务器的特定路径或者页面POST文件内容。
这个POST的HEADER或者QueryString里面起码要包含这几个参数:唯一标识码、当前文件块的区间。
7.服务端:收到跟随者线程的请求,以共享方式打开临时文件夹中的文件,写入当前文件块。
8.客户端,领导者线程:检测到文件块全部上传完毕,则向服务器某一个页面报告(如EndUpload.aspx),此文件上传结束,清理资源。
9.服务器:收到文件上传结束的通知,将文件从临时文件夹移动到需要的位置。
10. 服务器周期性地清理临时文件夹中的过期文件。
----------------------------------------------------------------
上面的流程是多线程分块并行上传的基本流程。也可以在此基础上进一步加入CRC32验证文件完整性的功能。如果要简化流程,不需要分块上传,只需要直接进行第6步操作就可以了。
对于第6部,在服务端,可以使用一个*.aspx页面或者一个IHttpHandler来处理请求。
参考下列代码,参数以及其它部分都已经略掉。
protected void Page_Load(object sender, EventArgs e)
{
Stream stream = Page.Request.InputStream;
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
// TO DO: Something else
}
protected void Page_Load(object sender, EventArgs e)
{
Stream stream = Page.Request.InputStream;
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
// TO DO: Something else
}
对于其它B/S平台,也是类似的方式。
客户端代码,我自己封装了一下,这里只列出关键代码。
view plain to clipboardprint?
void CHttpClient::OpenConnection( LPCTSTR lpszServer, UINT nPort)
{
CloseConnection();
m_hSession = ::InternetOpen( USER_AGENT
, INTERNET_OPEN_TYPE_PRECONFIG
, NULL
, NULL
, 0
);
if( !m_hSession )
throw CCustomException(_T("Error: Failed to connect to the server, InternetOpen failed."));
m_hConnect = ::InternetConnect( m_hSession
, lpszServer
, nPort
, NULL
, NULL
, INTERNET_SERVICE_HTTP
, NULL
, NULL
);
if( !m_hConnect )
throw CCustomException(_T("Error: Failed to connect to the server, InternetConnect failed."));
}
void CHttpClient::CloseConnection(void)
{
if( m_hSession )
{
::InternetCloseHandle(m_hSession);
m_hSession = NULL;
}
if( m_hConnect )
{
::InternetCloseHandle(m_hConnect);
m_hConnect = NULL;
}
}
void CHttpClient::PostBuffer( LPCTSTR lpszPath, LPBYTE lpBuffer, DWORD dwSize)
{
ASSERT( m_hSession && m_hConnect );
HINTERNET hRequest = ::HttpOpenRequest( m_hConnect
, _T("POST")
, lpszPath
, NULL
, NULL
, NULL
, INTERNET_FLAG_NO_CACHE_WRITE
, 0
);
if(!hRequest)
throw CCustomException(_T("Error: Failed to POST data to server, HttpOpenRequest failed."));
INTERNET_BUFFERS stBuffers = {0};
stBuffers.dwStructSize = sizeof(stBuffers);
stBuffers.Next = NULL;
stBuffers.lpcszHeader = NULL;
stBuffers.dwHeadersLength = 0;
stBuffers.dwHeadersTotal = 0;
stBuffers.lpvBuffer = NULL;
stBuffers.dwBufferLength = 0;
stBuffers.dwBufferTotal = dwSize;
stBuffers.dwOffsetLow = 0;
stBuffers.dwOffsetHigh = 0;
BOOL bRet = ::HttpSendRequestEx( hRequest, &stBuffers, NULL, 0, 0);
if(!bRet)
{
::InternetCloseHandle(hRequest);
throw CCustomException(_T("Error: Failed to POST data to server, HttpSendRequestEx failed."));
}
DWORD dwSent = 0;
DWORD dwBytesWritten = 0;
while(dwSent < dwSize)
{
bRet = ::InternetWriteFile( hRequest
, (LPBYTE)(lpBuffer + dwSent)
, dwSize - dwSent
, &dwBytesWritten
);
if( bRet )
dwSent += dwBytesWritten;
}
bRet = ::HttpEndRequest(hRequest, NULL, 0, 0);
::InternetCloseHandle(hRequest);
if( !bRet )
throw CCustomException(_T("Error: Failed to POST data to server, HttpEndRequest failed."));
}
void CHttpClient::OpenConnection( LPCTSTR lpszServer, UINT nPort)
{
CloseConnection();
m_hSession = ::InternetOpen( USER_AGENT
, INTERNET_OPEN_TYPE_PRECONFIG
, NULL
, NULL
, 0
);
if( !m_hSession )
throw CCustomException(_T("Error: Failed to connect to the server, InternetOpen failed."));
m_hConnect = ::InternetConnect( m_hSession
, lpszServer
, nPort
, NULL
, NULL
, INTERNET_SERVICE_HTTP
, NULL
, NULL
);
if( !m_hConnect )
throw CCustomException(_T("Error: Failed to connect to the server, InternetConnect failed."));
}
void CHttpClient::CloseConnection(void)
{
if( m_hSession )
{
::InternetCloseHandle(m_hSession);
m_hSession = NULL;
}
if( m_hConnect )
{
::InternetCloseHandle(m_hConnect);
m_hConnect = NULL;
}
}
void CHttpClient::PostBuffer( LPCTSTR lpszPath, LPBYTE lpBuffer, DWORD dwSize)
{
ASSERT( m_hSession && m_hConnect );
HINTERNET hRequest = ::HttpOpenRequest( m_hConnect
, _T("POST")
, lpszPath
, NULL
, NULL
, NULL
, INTERNET_FLAG_NO_CACHE_WRITE
, 0
);
if(!hRequest)
throw CCustomException(_T("Error: Failed to POST data to server, HttpOpenRequest failed."));
INTERNET_BUFFERS stBuffers = {0};
stBuffers.dwStructSize = sizeof(stBuffers);
stBuffers.Next = NULL;
stBuffers.lpcszHeader = NULL;
stBuffers.dwHeadersLength = 0;
stBuffers.dwHeadersTotal = 0;
stBuffers.lpvBuffer = NULL;
stBuffers.dwBufferLength = 0;
stBuffers.dwBufferTotal = dwSize;
stBuffers.dwOffsetLow = 0;
stBuffers.dwOffsetHigh = 0;
BOOL bRet = ::HttpSendRequestEx( hRequest, &stBuffers, NULL, 0, 0);
if(!bRet)
{
::InternetCloseHandle(hRequest);
throw CCustomException(_T("Error: Failed to POST data to server, HttpSendRequestEx failed."));
}
DWORD dwSent = 0;
DWORD dwBytesWritten = 0;
while(dwSent < dwSize)
{
bRet = ::InternetWriteFile( hRequest
, (LPBYTE)(lpBuffer + dwSent)
, dwSize - dwSent
, &dwBytesWritten
);
if( bRet )
dwSent += dwBytesWritten;
}
bRet = ::HttpEndRequest(hRequest, NULL, 0, 0);
::InternetCloseHandle(hRequest);
if( !bRet )
throw CCustomException(_T("Error: Failed to POST data to server, HttpEndRequest failed."));
}
调用示例:
const int BUFFER_SIZE = 1024000;
CHttpClient oClient;
oClient.OpenConnection( _T("127.0.0.1"), 4638 );
BYTE * pBuffer = new BYTE[BUFFER_SIZE];
for (UINT i = 0; i < BUFFER_SIZE; i++)
{
pBuffer[i] = i%0xFF;
}
oClient.PostBuffer( _T("/1/Default.aspx"), pBuffer, BUFFER_SIZE);
delete [] pBuffer;
说实话,是复制的,我也是个.NET程序员,我看了一下这个代码可以实现你的要求的哈!
E. asp.net mvc2.0 上传多个文件问题
for (fileCount = 0; fileCount < files.Count; fileCount++)
{
//定义访问客户端上传文件的对象
System.Web.HttpPostedFile postedFile = files[fileCount];
string FileType = postedFile.ContentType.ToString();//获取要上传的文件类型,验证文件头
string fileName, fileExtension;
//取得上传得文件名
fileName = System.IO.Path.GetFileName(postedFile.FileName);
//取得文件的扩展名
fileExtension = System.IO.Path.GetExtension(fileName);
//在上传文件不为空的情况下,验证文件名以及大小是否符合,如果不符合则不允许上传
if (((FileType == "text/plain" && fileExtension.ToLower() == ".txt") || (FileType == "application/x-zip-compressed" && fileExtension.ToLower() == ".zip") || (FileType == "application/octet-stream" && fileExtension.ToLower() == ".rar"))&&postedFile.ContentLength/1024<=1024)
{//在这里通过检查文件头与文件名是否匹配 从而限制了文件上传类型 注:可上传的类型有TXT,ZIP,RAR,且大小只能为1M一下
if (fileName != String.Empty)
{
fileName = RandomFileName() + fileExtension;
//上传的文件信息
strMsg.Append("上传的文件类型:" + postedFile.ContentType.ToString() + "<br>");
strMsg.Append("客户端文件地址:" + postedFile.FileName + "<br>");
strMsg.Append("上传文件的文件名:" + fileName + "<br>");
strMsg.Append("上传文件的大小为:" + postedFile.ContentLength + "字节<br>");
strMsg.Append("上传文件的扩展名:" + fileExtension + "<br><hr color=red>");
//保存到指定的文件夹
postedFile.SaveAs(Server.MapPath("public_file/" + UserName + "/") + fileName);
fileName = "";
}
}
比如这段代码来说,它不是通过for遍历了,然后不就可以得到你需要的文件了,你可以在里面在进行判断一下,不就OK了。!~~~~~
F. 求c#.net大文件上传解决方案支持分片断点上传
我简单点说一下我的想法:
使用base64将大文件进行字符串中亏处理,然后进行将字符串进行按规则进行分组
{ Key:'1',Data='byte',Index:1,EndStatus:'0' }
{ Key:'1',Data='byte',Index:2 ,EndStatus:'1' }
服务器使用redis或者其他缓存工具,服务器发现了EndStatus=1时,读取Redis中族培悄符合Key的集合数据,排序组装,然后byte转Stream存储文件
注意的点:B端文件转byte大小会增加30%,服务器端需兆渣要解开Request的最大请求大小