修訂如下大文件上傳(引發WebException:連接被意外關閉)
看帖子。
需要自動將文件上傳到網絡(無瀏覽器)。主機 - Mini File Host v1.2(如果這很重要)。沒有找到具體的API中的文件,所以起初我在Firebug嗅到瀏覽器請求如下:
Params : do
Value : verify
POST /upload.php?do=verify HTTP/1.1
Host: webfile.ukrwest.net
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; ru; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 (.NET CLR 4.0.20506)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://filehoster.awardspace.com/index.php
Content-Type: multipart/form-data; boundary=---------------------------27368237179714
Content-Length: 445
-----------------------------27368237179714
Content-Disposition: form-data; name="upfile"; filename="Test.file"
Content-Type: application/octet-stream
12345678901011121314151617sample text
-----------------------------27368237179714
Content-Disposition: form-data; name="descr"
-----------------------------27368237179714
Content-Disposition: form-data; name="pprotect"
-----------------------------27368237179714--
在這裏我們可以看到參數,標題,內容類型和信息塊(1 - 文件名和類型, 2 - 文件內容,3 - 附加參數 - 描述和密碼,不一定適用)。 所以我創建了一個模擬這樣的行爲一步一步的類:對網址的HttpWebRequest,申請需要的參數請求,形成與StringBuilder的請求字符串,並將它們轉換爲字節數組,使用FileStream讀取文件,把所有這些東西到MemoryStream,然後寫它請求(從CodeProject上的文章的主要部分代碼,它將文件上傳到Rapidshare主機)。 整潔,但...它似乎並沒有工作:(因爲它返回初始上傳頁面,而不是結果頁面的鏈接,我可以解析並呈現給用戶... 這裏是主要的方法一類上傳:
// Step 1 - request creation
private HttpWebRequest GetWebrequest(string boundary)
{
Uri uri = new Uri("http://filehoster.awardspace.com/index.php?do=verify");
System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
httpWebRequest.CookieContainer = _cookies;
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2; ru; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 (.NET CLR 4.0.20506)";
httpWebRequest.Referer = "http://filehoster.awardspace.com/index.php";
httpWebRequest.Method = "POST";
httpWebRequest.KeepAlive = true;
httpWebRequest.Timeout = -1;
//httpWebRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
httpWebRequest.Headers.Add("Accept-Charset", "windows-1251,utf-8;q=0.7,*;q=0.7");
httpWebRequest.Headers.Add("Accept-Encoding", "gzip,deflate");
httpWebRequest.Headers.Add("Accept-Language", "ru,en-us;q=0.7,en;q=0.3");
//httpWebRequest.AllowAutoRedirect = true;
//httpWebRequest.ProtocolVersion = new Version(1,1);
//httpWebRequest.SendChunked = true;
//httpWebRequest.Headers.Add("Cache-Control", "no-cache");
//httpWebRequest.ServicePoint.Expect100Continue = false;
return httpWebRequest;
}
// Step 2 - first message part (before file contents)
private string GetRequestMessage(string boundary, string FName, string description, string password)
{
System.Text.StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("--");
stringBuilder.Append(boundary);
stringBuilder.Append("\r\n");
stringBuilder.Append("Content-Disposition: form-data; name=\"");
stringBuilder.Append("upfile");
stringBuilder.Append("\"; filename=\"");
stringBuilder.Append(FName);
stringBuilder.Append("\"");
stringBuilder.Append("\r\n");
stringBuilder.Append("Content-Type: application/octet-stream");
stringBuilder.Append("\r\n");
return stringBuilder.ToString();
}
// Step 4 - additional request parameters. Step 3 - reading file is in method below
private string GetRequestMessageEnd(string boundary)
{
System.Text.StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(boundary);
stringBuilder.Append("\r\n");
stringBuilder.Append("Content-Disposition: form-data; name=\"descr\"");
stringBuilder.Append("\r\n");
stringBuilder.Append("\r\n");
stringBuilder.Append("Default description");
stringBuilder.Append("\r\n");
stringBuilder.Append(boundary);
stringBuilder.Append("\r\n");
stringBuilder.Append("Content-Disposition: form-data; name=\"pprotect\"");
stringBuilder.Append("\r\n");
stringBuilder.Append("\r\n");
stringBuilder.Append("");
stringBuilder.Append("\r\n");
stringBuilder.Append(boundary);
stringBuilder.Append("--");
//stringBuilder.Append("\r\n");
//stringBuilder.Append(boundary);
//stringBuilder.Append("\r\n");
return stringBuilder.ToString();
}
// Main method
public string ProcessUpload(string FilePath, string description, string password)
{
// Chosen file information
FileSystemInfo _file = new FileInfo(FilePath);
// Random boundary generation
DateTime dateTime2 = DateTime.Now;
long l2 = dateTime2.Ticks;
string _generatedBoundary = "----------" + l2.ToString("x");
// Web request creation
System.Net.HttpWebRequest httpWebRequest = GetWebrequest(_generatedBoundary);
// Main app block - form and send request
using (System.IO.FileStream fileStream = new FileStream(_file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] bArr1 = Encoding.ASCII.GetBytes("\r\n--" + _generatedBoundary + "\r\n");
// Generating pre-content post message
string firstPostMessagePart = GetRequestMessage(_generatedBoundary, _file.Name, description, password);
// Writing first part of request
byte[] bArr2 = Encoding.UTF8.GetBytes(firstPostMessagePart);
Stream memStream = new MemoryStream();
memStream.Write(bArr1, 0, bArr1.Length);
memStream.Write(bArr2, 0, bArr2.Length);
// Writing file
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
// Generating end of a post message
string secondPostMessagePart = GetRequestMessageEnd(_generatedBoundary);
byte[] bArr3 = Encoding.UTF8.GetBytes(secondPostMessagePart);
memStream.Write(bArr3, 0, bArr3.Length);
// Preparing to send
httpWebRequest.ContentLength = memStream.Length;
fileStream.Close();
Stream requestStream = httpWebRequest.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
// Sending request
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
}
// Delay (?)
System.Threading.Thread.Sleep(5000);
// Getting response
string strResponse = "";
using (Stream stream = httpWebRequest.GetResponse().GetResponseStream())
using (StreamReader streamReader = new StreamReader(stream/*, Encoding.GetEncoding(1251)*/))
{
strResponse = streamReader.ReadToEnd();
}
return strResponse;
}
玩弄ProtocolVersion(1.0,1.1),AllowAutoRedirect(真/假),即使知道ServicePoint.Expect100Continue(假)並沒有得到響應之前,即使是5秒超時解決的問題(內容類型「octet-stream」被選擇用於上傳任何文件(可以使用一些開關用於最流行的jpg/zip/rar/doc等等,但這似乎是普遍的)。邊界是從計時器滴答隨機產生的,沒有什麼大不了的別的呢? :/ 我可以放棄並忘記這一點,但我覺得我很接近解決和然後忘掉它:P。 如果您需要在整個應用程序運行和調試 - 這裏是(70KB,壓縮C#2.0 VS2k8解決方案,無廣告,無病毒):
@Mediafire @FileQube @FileDropper
你是什麼意思「顯示主機的主頁」?你能詳細說明你得到的實際錯誤嗎?什麼不工作? – fretje 2009-06-29 23:05:41
帶有「選擇文件」框並上傳按鈕的頁面: http://i.piccy.info/i3/74/b5/3089a82aa091a0d975b987f1bedd.png 不是包含指向文件鏈接的頁面: http://i.piccy .info/i3/30/48/b66db6dee2e353949bd5d5269557.png 我認爲在發送數據並獲得結果的步驟中不起作用。即使使用AllowAutoRedirect param = true並初始化CookieContainer,重定向也不會發生。 – Jaded 2009-06-30 08:24:45