写入请求流时请求被中止错误 [英] The request was aborted error while writing to request stream

查看:224
本文介绍了写入请求流时请求被中止错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public HttpWebResponse PushFileToWistia(byte [] contentFileByteArray,string fileName)
{
StringBuilder postDataBuilder = new StringBuilder();
postDataBuilder.Append(我正在追加所有的wistia配置和设置在这里);
byte [] postData = null;
using(MemoryStream postDataStream = new MemoryStream())
{
byte [] postDataBuffer = Encoding.UTF8.GetBytes(postDataBuilder.ToString());
postDataStream.Write(postDataBuffer,0,postDataBuffer.Length);
postDataStream.Write(contentFileByteArray,0,contentFileByteArray.Length);
postDataBuffer = Encoding.UTF8.GetBytes(\r\\\
--+ boundary + - );
postDataStream.Write(postDataBuffer,0,postDataBuffer.Length);
postData = postDataStream.ToArray();
}

ServicePointManager.Expect100Continue = false;
HttpWebRequest request =(HttpWebRequest)WebRequest.Create(AppConfig.WistiaCustomCourseBucket);
request.Method =POST;
request.Expect = String.Empty;
request.Headers.Clear();
request.ContentType =multipart / form-data; boundary =+ boundary;
request.ContentLength = postData.Length;

stream requestStream = request.GetRequestStream();
requestStream.Write(postData,0,postData.Length); //用于文件> 100MB这个调用抛出错误 - 请求被中止。该请求被取消。
requestStream.Flush();
requestStream.Close();

HttpWebResponse response =(HttpWebResponse)request.GetResponse();
返回响应;



$ b $ p
$ b

以上代码适用于视频文件mp4小于50mb。但是,当我尝试上传一个100MB的文件,它抛出异常(请求被中止。)我需要支持文件大小高达1.5GB所以现在我不知道这种方法是否正确的这样一个大文件上传。任何建议在正确的方向将有帮助...谢谢(我想上传文件到Wistia服务器)
在这一行抛出异常
- requestStream.Write(postData,0, postData.Length);

我尝试了更改web.config设置,但没有成功:
httpRuntime targetFramework =4.5maxRequestLength =2048576 executionTimeout =12000requestLengthDiskThreshold =1024

异步调用-------

  MemoryStream wistiaFileStream = null; 
using(MemoryStream postDataStream = new MemoryStream())
{
postDataStream.Write(contentFileByteArray,0,contentFileByteArray.Length);
wistiaFileStream = postDataStream;
postDataStream.Flush();
postDataStream.Close();
}

stream requestStream = await request.GetRequestStreamAsync();
等待requestStream.WriteAsync(wistiaMetadata,0,wistiaMetadata.Length); (wistiaFileStream)
{
byte [] wistiaFileBuffer =新字节[500 * 1024];


int wistiaFileBytesRead = 0;
$ b $而(
(wistiaFileBytesRead =
等待wistiaFileStream.ReadAsync(wistiaFileBuffer,0,wistiaFileBuffer.Length))!= 0)
{
await requestStream .WriteAsync(wistiaFileBuffer,0,wistiaFileBytesRead);
await requestStream.FlushAsync();
}
await requestStream.WriteAsync(requestBoundary,0,requestBoundary.Length);


解决方案

em> async ,并直接从文件系统写入文件以避免1.5GB内存的三重缓冲(以下警告未经测试)。

  public async Task< HttpWebResponse> PushFileToWistiaAsync(string contentFilePath)
{
string boundary =---------------------------+ DateTime.Now .Ticks.ToString( X);
string contentBoundary =\r\\\
--+ boundary +\r\\\
;

StringBuilder wistiaMetadataBuilder = new StringBuilder();
wistiaMetadataBuilder.Append( - + boundary +\r\\\
);
//追加所有wistia配置并在这里设置

byte [] wistiaMetadata = Encoding.UTF8.GetBytes(wistiaMetadataBuilder.ToString());
byte [] requestBoundary = Encoding.UTF8.GetBytes(contentBoundary);

ServicePointManager.Expect100Continue = false;

HttpWebRequest request =(HttpWebRequest)WebRequest.Create(AppConfig.WistiaCustomCourseBucket);
request.Method =POST;
request.Headers.Clear();
request.Expect = String.Empty;
request.ContentType =multipart / form-data; boundary =+ boundary;

stream requestStream = await request.GetRequestStreamAsync();
等待requestStream.WriteAsync(wistiaMetadata,0,wistiaMetadata.Length);
using(FileStream wistiaFileStream = new FileStream(contentFilePath,FileMode.Open,FileAccess.Read))
{
byte [] wistiaFileBuffer = new byte [500 * 1024];
int wistiaFileBytesRead = 0; ((wistiaFileBytesRead =等待wistiaFileStream.ReadAsync(wistiaFileBuffer,0,wistiaFileBuffer.Length))!= 0)

等待requestStream.WriteAsync(wistiaFileBuffer,0,wistiaFileBytesRead );
await requestStream.FlushAsync();


await requestStream.WriteAsync(requestBoundary,0,requestBoundary.Length);

return(HttpWebResponse)(await request.GetResponseAsync());



$ b

你应该使用缓冲区大小,一次读取的数据量和 request.SendChunked 来实现合理的性能。

这是另一种方法(不是异步,所以可能是最差的可伸缩性)从缓冲区到请求:

$ $ $











$ b $ public $ { ---------------------------+ DateTime.Now.Ticks.ToString(x);
string contentBoundary =\r\\\
--+ boundary +\r\\\
;

StringBuilder wistiaMetadataBuilder = new StringBuilder();
wistiaMetadataBuilder.Append( - + boundary +\r\\\
);
//追加所有wistia配置并在这里设置

byte [] wistiaMetadata = Encoding.UTF8.GetBytes(wistiaMetadataBuilder.ToString());
byte [] requestBoundary = Encoding.UTF8.GetBytes(contentBoundary);

ServicePointManager.Expect100Continue = false;

HttpWebRequest request =(HttpWebRequest)WebRequest.Create(AppConfig.WistiaCustomCourseBucket);
request.Method =POST;
request.Headers.Clear();
request.Expect = String.Empty;
request.ContentType =multipart / form-data; boundary =+ boundary;
request.ContentLength = wistiaMetadata.Length + contentFileByteArray.Length + requestBoundary.Length

//你可以使用SendChunked和AllowWriteStreamBuffering来控制你发送的块的大小和性能
//request.SendChunked = true;
//request.AllowWriteStreamBuffering = false;

int contentFileChunkSize = 500 * 1024;
int contentFileBytesRead = 0;

stream requestStream = request.GetRequestStream();
requestStream.Write(wistiaMetadata,0,wistiaMetadata.Length);
while(contentFileBytesRead< contentFileByteArray.Length)
{
if((contentFileBytesRead + contentFileChunkSize)> contentFileByteArray.Length)
{
contentFileChunkSize = contentFileByteArray.Length - contentFileBytesRead;
}

requestStream.Write(contentFileByteArray,contentFileBytesRead,contentFileChunkSize);
requestStream.Flush();

contentFileBytesRead + = contentFileChunkSize;
}
requestStream.Write(requestBoundary,0,requestBoundary.Length);
requestStream.Close();

//你可能需要玩request.Timeout这里
return(HttpWebResponse)request.GetResponse();





$ b

另外,如果你在web应用程序中这样做,并且想要使用异步方法需要一直异步/等待(async控制器中的异步操作等)。

一般情况下,我会劝阻做这个请求处理的一部分Web应用程序(从用户角度观察的总时间将是上传到您的应用程序,然后到Wistia可能远远超过客户端超时允许)的总和。在这种情况下,通常最好保存文件并安排一些其他后台任务来完成上传作业。


public HttpWebResponse PushFileToWistia(byte[] contentFileByteArray, string fileName)
    {
        StringBuilder postDataBuilder = new StringBuilder();
        postDataBuilder.Append("I am appending all the wistia config and setting here");
        byte[] postData = null;
        using (MemoryStream postDataStream = new MemoryStream())
        {
            byte[] postDataBuffer = Encoding.UTF8.GetBytes(postDataBuilder.ToString());
            postDataStream.Write(postDataBuffer, 0, postDataBuffer.Length);
            postDataStream.Write(contentFileByteArray, 0, contentFileByteArray.Length);
            postDataBuffer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--");
            postDataStream.Write(postDataBuffer, 0, postDataBuffer.Length);
            postData = postDataStream.ToArray();
        }

        ServicePointManager.Expect100Continue = false;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(AppConfig.WistiaCustomCourseBucket);
        request.Method = "POST";
        request.Expect = String.Empty;
        request.Headers.Clear();
        request.ContentType = "multipart/form-data; boundary=" + boundary;
        request.ContentLength = postData.Length;

        Stream requestStream = request.GetRequestStream();
        requestStream.Write(postData, 0, postData.Length);  //for file > 100mb this call throws and error --the requet was aborted. the request was canceled. 
        requestStream.Flush();
        requestStream.Close();

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        return response;
        }

The above code works for video file mp4 less then 50mb. But when I try to upload a 100mb file it throws and exception (Request was aborted.) I need to support file size up to 1.5gb So now I am not sure if this approach is correct for such a big file size upload. Any suggestions in the right direction will be helpful...thanks(I am trying to upload the file to Wistia Server) The exception is thrown at this line -- requestStream.Write(postData, 0, postData.Length);

I have tried changing the web.config setting but didn't work: httpRuntime targetFramework="4.5" maxRequestLength="2048576" executionTimeout="12000" requestLengthDiskThreshold="1024"

------Async Call-------

       MemoryStream wistiaFileStream = null;
        using (MemoryStream postDataStream = new MemoryStream())
        {
            postDataStream.Write(contentFileByteArray, 0, contentFileByteArray.Length);
            wistiaFileStream = postDataStream;
            postDataStream.Flush();
            postDataStream.Close();
        }

        Stream requestStream = await request.GetRequestStreamAsync();
        await requestStream.WriteAsync(wistiaMetadata, 0, wistiaMetadata.Length);

 using (wistiaFileStream)
        {
            byte[] wistiaFileBuffer = new byte[500*1024];
            int wistiaFileBytesRead = 0;

            while (
                (wistiaFileBytesRead =
                    await wistiaFileStream.ReadAsync(wistiaFileBuffer, 0, wistiaFileBuffer.Length)) != 0)
            {
                await requestStream.WriteAsync(wistiaFileBuffer, 0, wistiaFileBytesRead);
                await requestStream.FlushAsync();
            }
            await requestStream.WriteAsync(requestBoundary, 0, requestBoundary.Length);
        }

解决方案

I would suggest moving to async and write file directly from file system to request in order to avoid triple buffering of 1.5GB in memory (warning below is not tested).

public async Task<HttpWebResponse> PushFileToWistiaAsync(string contentFilePath)
{
    string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
    string contentBoundary = "\r\n--" + boundary + "\r\n";

    StringBuilder wistiaMetadataBuilder = new StringBuilder();
    wistiaMetadataBuilder.Append("--" + boundary + "\r\n");
    // Append all the wistia config and setting here

    byte[] wistiaMetadata = Encoding.UTF8.GetBytes(wistiaMetadataBuilder.ToString());
    byte[] requestBoundary = Encoding.UTF8.GetBytes(contentBoundary);

    ServicePointManager.Expect100Continue = false;

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(AppConfig.WistiaCustomCourseBucket);
    request.Method = "POST";
    request.Headers.Clear();
    request.Expect = String.Empty;
    request.ContentType = "multipart/form-data; boundary=" + boundary;

    Stream requestStream = await request.GetRequestStreamAsync();
    await requestStream.WriteAsync(wistiaMetadata, 0, wistiaMetadata.Length);
    using (FileStream wistiaFileStream = new FileStream(contentFilePath, FileMode.Open, FileAccess.Read))
    {
        byte[] wistiaFileBuffer = new byte[500 * 1024];
        int wistiaFileBytesRead = 0;

        while ((wistiaFileBytesRead = await wistiaFileStream.ReadAsync(wistiaFileBuffer, 0, wistiaFileBuffer.Length)) != 0)
        {
            await requestStream.WriteAsync(wistiaFileBuffer, 0, wistiaFileBytesRead);
            await requestStream.FlushAsync();
        }
    }
    await requestStream.WriteAsync(requestBoundary, 0, requestBoundary.Length);

    return (HttpWebResponse)(await request.GetResponseAsync());
}

You should play with buffer sizes, amount of data you read at once and request.SendChunked to achieve reasonable performance.

Here is another approach (not asynchronous so possibly worst scalability) which wirtes directly from buffer to request:

public HttpWebResponse PushFileToWistia(byte[] contentFileByteArray)
{
    string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
    string contentBoundary = "\r\n--" + boundary + "\r\n";

    StringBuilder wistiaMetadataBuilder = new StringBuilder();
    wistiaMetadataBuilder.Append("--" + boundary + "\r\n");
    // Append all the wistia config and setting here

    byte[] wistiaMetadata = Encoding.UTF8.GetBytes(wistiaMetadataBuilder.ToString());
    byte[] requestBoundary = Encoding.UTF8.GetBytes(contentBoundary);

    ServicePointManager.Expect100Continue = false;

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(AppConfig.WistiaCustomCourseBucket);
    request.Method = "POST";
    request.Headers.Clear();
    request.Expect = String.Empty;
    request.ContentType = "multipart/form-data; boundary=" + boundary;
    request.ContentLength = wistiaMetadata.Length + contentFileByteArray.Length + requestBoundary.Length

    // You can play with SendChunked and AllowWriteStreamBuffering to control the size of chunks you send and performance
    //request.SendChunked = true;
    //request.AllowWriteStreamBuffering = false;

    int contentFileChunkSize = 500 * 1024;
    int contentFileBytesRead = 0;

    Stream requestStream = request.GetRequestStream();
    requestStream.Write(wistiaMetadata, 0, wistiaMetadata.Length);
    while (contentFileBytesRead < contentFileByteArray.Length)
    {
        if ((contentFileBytesRead + contentFileChunkSize) > contentFileByteArray.Length)
        {
            contentFileChunkSize = contentFileByteArray.Length - contentFileBytesRead;
        }

        requestStream.Write(contentFileByteArray, contentFileBytesRead, contentFileChunkSize);
        requestStream.Flush();

        contentFileBytesRead += contentFileChunkSize;
    }
    requestStream.Write(requestBoundary, 0, requestBoundary.Length);
    requestStream.Close();

    // You might need to play with request.Timeout here
    return (HttpWebResponse)request.GetResponse();
}

Also if you doing this in web application and you want to use asynchronous approach you need to "async/await" all the way up (so async action in async controller etc.).

In general I would discourage doing this as part of request handling in web application (the total time observed from user perspective would be a sum of uploading to your app and then to Wistia which might be much more than client timeout allows). In such case it is usually better to save the file and schedule some other "background task" to do the upload job.

这篇关于写入请求流时请求被中止错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆