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的最大請求大小