2017-04-19 33 views
0
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; 
     } 

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

我试图改变的web.config的设置,但没有奏效: 的httpRuntime targetFramework = “4.5” 的maxRequestLength = “2048576” executionTimeout = “12000” requestLengthDiskThreshold = “1024”

----- -async呼叫-------

 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); 
     } 

回答

1

我建议移动到异步并直接从文件系统写入文件,以避免在存储器1.5GB的三重缓冲请求(下面警告是不测试)。

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()); 
} 

你应该和缓冲区大小,你读一次,并request.SendChunked实现合理的性能数据量播放。

这里是另一种方法(不是异步那么可能是最坏的可扩展性),这直接wirtes从缓冲区要求:

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(); 
} 

此外,如果你的Web应用程序这样做的,你要使用异步方法,你需要“异步/等待“(async控制器中的异步操作等)。

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

+0

我没有从磁盘读取文件我从HTML文件上传中获取文件。我不得不修改上面的解决方案,以适应我的代码。它正确运行异步调用witohut任何错误。它将成功消息返回给客户端Ux。但我没有看到WISTIA服务器上的任何文件..它运行如此之快的1.5 GB文件,我不认为它实际上发送文件内容WISTIA ..有没有一种方法,我们可以阻止所有其他的执行,直到我们完成异步调用并获得成功状态...我在问题 – Scorpio

+0

@Scorpio中添加了编辑的代码您的实现没有抛出异常吗?如果我正确阅读,当您开始阅读时,wistiaFileStream会关闭。如果你真的必须将文件保存为字节数组(这是危险的,因为在10个并行请求的情况下,最终可能会分配15 GB),我建议直接从该数组写入请求。我会尝试编辑我的答案以表明这一点。 – tpeczek

+0

@Scorpio为不同的方法和一些一般建议添加了一个示例 – tpeczek

相关问题