大文件上传(WebException:连接意外关闭)

2024-01-20

UPDATED

看帖子#3 https://stackoverflow.com/questions/1060966/big-files-uploading-webexception-the-connection-was-closed-unexpectedly/1066265#1066265 below.

需要自动将文件上传到网络(无需浏览器)。主持人 -(如果这确实重要的话)。在文档中没有找到具体的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 - 附加参数 - 描述和密码,不一定适用)。 因此,我创建了一个逐步模拟此类行为的类:在 url 上使用 HttpWebRequest,将所需的参数应用于请求,使用 StringBuilder 形成请求字符串并将其转换为字节数组,使用 FileStream 读取文件,将所有内容放入MemoryStream,然后将其写入请求(代码的主要部分取自 CodeProject 上的一篇文章,其中将文件上传到 Rapidshare 主机)。 整洁,但是...它似乎不起作用:(。结果它返回初始上传页面,而不是带有我可以解析并呈现给用户的链接的结果页面... 以下是 Uploader 类的主要方法:

// 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 等使用一些开关,但这似乎是通用的)。边界是从计时器滴答声中随机生成的,没什么大不了的。还有什么? :/ 我可以放弃并忘记这个,但我觉得我已经很接近解决问题了then忘记它吧:P。 如果您需要运行和调试整个应用程序 - 这里是(70kb,压缩的 C# 2.0 VS2k8 解决方案,无广告,无病毒):

@Mediafire http://www.mediafire.com/download.php?no1tlmln3yy @FileQube http://www.fileqube.com/file/RZPUGRwxE203936 @FileDropper http://www.filedropper.com/uploader


更新:不,没有重定向。

截屏 http://i.piccy.info/i3/ab/2d/abb26ac7f33c80910040ba58e5f6.png

Read RFC2388 http://www.faqs.org/rfcs/rfc2388.html重写了几次代码,它终于成功了(我猜问题出在 utf 读取尾随边界而不是正确的 7 位 ascii)。万岁?不:(。只传输小文件,大文件会抛出“连接意外关闭”。

System.Net.WebException was unhandled by user code
  Message="The underlying connection was closed: The connection was closed unexpectedly."
  Source="Uploader"
  StackTrace:
   at Uploader.Upload.ProcessUpload(String FilePath, String description, String password) in F:\MyDocuments\Visual Studio 2008\Projects\Uploader\Uploader.cs:line 96
   at Uploader.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in F:\MyDocuments\Visual Studio 2008\Projects\Uploader\Form1.cs:line 45
   at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument) 

我知道这是 .net 堆栈的一个错误,并且存在很少的解决方案:

  1. 增加两者Timeout and ReadWriteTimeout一个请求的

  2. assign request.KeepAlive = false and System.Net.ServicePointManager.Expect100Continue = false

  3. set ProtocolVersion to 1.0但它们中的任何一个或全部都对我的情况没有帮助。有任何想法吗?

EDIT- 源代码:

// .. request created, required params applied
httpWebRequest.ProtocolVersion = HttpVersion.Version10; // fix 1
httpWebRequest.KeepAlive = false; // fix 2
httpWebRequest.Timeout = 1000000000; // fix 3
httpWebRequest.ReadWriteTimeout = 1000000000; // fix 4
// .. request processed, data written to request stream
string strResponse = "";            
try
{
    using (WebResponse httpResponse = httpWebRequest.GetResponse()) // error here
        {
            using (Stream responseStream = httpResponse.GetResponseStream())
            {
                using (StreamReader streamReader = new StreamReader(responseStream))
                    {
                        strResponse = streamReader.ReadToEnd();
                    }
                }
            }
        }
catch (WebException exception)
{
    throw exception;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大文件上传(WebException:连接意外关闭) 的相关文章

随机推荐

  • Apache Spark GCS 连接器的速率限制

    我在带有 Google Cloud Storage 连接器的 Google Compute Engine 集群上使用 Spark 而不是 HDFS 如受到推崇的 https cloud google com hadoop google cl
  • 更好的方法来检查条件而不是重复 Case When

    这是我的表格 Member Id UserId UserName Email Status Id MemberType Id CustomerProfile Id Member Id FirstName LastName SSN Gende
  • 提升灵气期待

    我对灵气比较陌生 正在尝试解析一种类似汇编语言 例如 我想解析 Func Ident Mov name hello Push 5 Exit 到目前为止 一切都很好 我可以正确解析它 然而 错误处理程序有时会出现奇怪的错误位置 以下面的错误代
  • Laravel 模板/控制器在保存时未更新

    我正在 OS X 上运行 Laravel 4 作为一个简单的应用程序 基本上 在我保存对这些文件的更改后 对控制器和模板的更改在很长一段时间内不会生效 例如 我向 app views index blade php 添加一个单词 并且在不断
  • javascript bookmarklet 隐藏当前网页中的所有图像?

    我想创建一个简单的书签 隐藏我正在浏览的当前网站的所有图像 javascript body getElementsByTagName img style visibility hidden 那不行吗 我想知道我做错了什么 感谢您的帮助 您需
  • 当应用程序长时间进入后台时,Firestore 监听器被杀死

    在我的应用程序中 每当用户登录时 我都会监听 Firestore 查询 应用程序进入后台一段时间后 监听器将被取消 并且客户端不会收到任何新更改的通知 如何知道监听器是否已被 SDK 取消 处理这个问题的正确方法是什么 在大多数操作系统上
  • 在生产服务器中拥有 Git 存储库是一个坏主意吗

    我们有 Windows Server 2012 Apache PHP 和 MySQL 服务器有点乱 我想要的事情之一是跟踪代码的更改 通常我不会在服务器上设置 Git 而是在本地计算机上进行开发 然后使用 SSH 将更改部署到生产服务器 然
  • 在 WPF 中使用枚举作为依赖属性

    我尝试在自定义控件中使用枚举类型作为依赖属性 但总是收到错误 public enum PriceCategories First 1 Second 2 Third 3 Fourth 4 Fifth 5 Sixth 6 public stat
  • Blackberry Storm 模拟器 - TouchGesture 事件未触发,如何让滑动功能正常工作?

    我一直在玩 Storm Emulator 和 4 7 JDE 我一生都不知道如何在模拟器中触发手势事件 下面是 RIM 示例应用程序 EmbeddedMapDemo 的触摸事件代码 这看起来很简单 但 touchGesture getEve
  • 是否可以使用一个重载运算符来实现另一个运算符重载?

    例如 如果我重载了 运算符 myClass operator const myClass rhs 并且还重载了 运算符 myClass operator const myClass rhs 两个运营商都工作正常 我可以在 运算符重载中使用这
  • asp.net mvc 中数据库上下文类的用途是什么

    我是 MVC 新手 并且已经完成了一些教程来掌握它的窍门 但在其中一些教程中我遇到了一个带有 DbContext 类的示例asp net mvc5 与 EF6 教程 https www asp net mvc overview gettin
  • 使用 i18n 进行 Vuelidate:在区域设置消息中找不到密钥

    因此 在我的 i18n validators js 文件中 我想将带有翻译消息的验证器导出为我选择的语言 并在我的 vue 组件中使用它们来验证表单 My code import as VuelidateValidators from ht
  • C# 读取xml文件

    我正在尝试拉
  • 如何绑定内联匿名函数?

    我在尝试着bind ie bind this 内联匿名回调函数object如何做呢 简化示例 var object property function this id abc this binds to the object aFuncti
  • D3:使用 d3.max 获取包含对象?

    我有以下数据 一个对象数组 var data x 0 y0 0 y 100 x 1 y0 0 y 150 x 2 y0 50 y 100 x 3 y0 50 y 150 我想找到之间差异最大的对象y and y0 使用 D3 我可以这样做以
  • Netbeans 中的拆分窗口

    我正在尝试拆分我的窗口 以便我可以在 1 个屏幕上拥有 2 个不同的类或其他内容 但它只会拆分同一类 文件 其他内容的窗口 我已经使用 netbeans 多年了 但仍然无法做到这一点 这可能吗 您没有具体提及您正在使用哪个版本的 NetBe
  • SQL Server SMO - 备份 - 如何确定失败/成功?

    如果使用 SMO 执行备份 成功完成后 我测试 SqlError 是否为 null 认为备份已完成且没有错误 但是 正如您所看到的 它实际上返回了 0 类编号 3014 的错误 这意味着成功 所以问题是 问 如何确定备份是否成功完成 以及如
  • 与 jasperReports 完全混淆

    在开始工作前两天 我才刚刚接触 jasper 我下载了 jasperReports 和 iReports 并在我的 salesforce 帐户中安装了 iReports 并安装了 jasper4salesforce 但没有找到任何 jasp
  • jQuery - 内联调用函数

    我正在尝试将一个变量传递给内联 jQuery 函数 即 使用onMouseOver function 在实际链接内 这是图像映射中的区域标记 仅当我将其放在之前时才会调用该函数 document ready function 行 但这样做会
  • 大文件上传(WebException:连接意外关闭)

    UPDATED 看帖子 3 https stackoverflow com questions 1060966 big files uploading webexception the connection was closed unexp