2010-01-21 50 views
0

使用Silverlight 3构建文件上传应用程序。它可以上传几乎任何大小的文件 - 它可以在4GB的文件下运行(取决于环境)。它会上传文件块,以便发生任何事情时,可以从最近的块恢复上传。Silverlight文件上传内存问题

在上传大文件时,上传不起作用的情况是在IE和Chrome中。他们似乎有记忆问题。在Firefox中,内存使用情况是一条锯齿形的线条 - 如果它正在读取文件块,上传文件,丢弃文件,然后在下一个块上重新开始,则会出现这种情况。 IE和Chrome似乎坚持大块。一旦可用RAM用完,最终会抛出OutOfMemoryException。

到目前为止,我已经尝试更改文件流和webrequest流大小,缓冲区等。我试图只生成字节,而不是从文件流中读取 - 相同的问题。我试过一次只写一个块,而不是现在使用的4KB缓冲区 - 同样的问题。

关于可能发生什么的任何想法? IE和Chrome是不是垃圾收集,以摆脱不需要的块?或者是否有一些http请求头我应该使用?关于如何查明内存使用的一些想法 - 在IE本身或Silverlight插件中?

+0

@ndim感谢您解决输入错误 – cofiem

+1

您可以尝试模拟上传,而不实际发送任何数据,而只是读取文件块,转换为字节,并继续? –

+0

不错的主意......当我可以的时候我会回到这个位置,并尝试一下。 – cofiem

回答

0

即使升级到Silverlight 4后,我也无法确定发生了什么。对不起,我无法提供更多帮助。

1

当我想从Silverlight应用程序导出数据到.csv文件时,我遇到了非常相同的情况。在Internet Explorer中,我无法保存文件,因为请求没有发送到我用来从中检索数据的http处理程序。

最初的代码是这样的:

 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url, UriKind.Absolute)); 
      request.BeginGetResponse(new AsyncCallback(ReadExportHandlerCallback), request); 

,但它并没有在IE浏览器。 Fiddler向我展示了请求不会发送到http处理程序,我不知道为什么会发生这种情况。

我已经与下一个解决方案交流:使用流(内存,文件)为处理程序和异步方法BeginRequestStream()和EndGetRequestStream()发出请求。

// other code. 
    { 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url, UriKind.Absolute)); 

      MemoryStream mStream = new MemoryStream(); 
      var uploadRequest = new UploadRequest 
        { 
         MemoryStream = mStream, 
         Request = request 
        }; 

      request.Method = "POST"; 
      request.BeginGetRequestStream(OnGetRequestStream, uploadRequest);     
    } 


    public void OnGetRequestStream(IAsyncResult result) 
    { 
     var uploadRequest = (UploadRequest)result.AsyncState;    
     uploadRequest.MemoryStream.Seek(0, SeekOrigin.Begin); 
     try 
     { 
      // upload bytes to the server 
      using (var stream = uploadRequest.Request.EndGetRequestStream(result)) 
      { 
       var buffer = new byte[uploadRequest.MemoryStream.Length]; 
       int bytesRead; 

       while ((bytesRead = uploadRequest.MemoryStream.Read(buffer, 0,     buffer.Length)) != 0) 
       { 
        stream.Write(buffer, 0, bytesRead); 
       } 
      } 

      // async get response     
      uploadRequest.Request.BeginGetResponse(new AsyncCallback(ReadExportHandlerCallback), uploadRequest); 
     } 
     catch (Exception) 
     { 

     } 
     finally 
     { 
      // ensure file is properly closed after sending either succeeded or failed 
      uploadRequest.MemoryStream.Close(); 
     } 
    }  

    private void ReadExportHandlerCallback(IAsyncResult asynchronousResult) 
    {    
     var uploadRequest = (UploadRequest)asynchronousResult.AsyncState; 
     var response = (HttpWebResponse)uploadRequest.Request.EndGetResponse(asynchronousResult); 

     using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) 
     { 
      _data = streamReader.ReadToEnd(); 
      _dataReceived = true; 
     }    
    } 

的UploadRequest类是含有2个属性的自定义类:一个MemoryStream和HttpWebRequest的。

public class UploadRequest 
{ 
    #region Fields 

    private MemoryStream _memoryStream; 
    private HttpWebRequest _httpWebRequest; 

    #endregion 

    #region Properties 

    /// <summary> 
    /// The stream that will be sent to the handler. 
    /// </summary> 
    public MemoryStream MemoryStream 
    { 
     get 
     { 
      return _memoryStream; 
     } 
     set 
     { 
      _memoryStream = value; 
     } 
    } 

    /// <summary> 
    /// The request that contains the stream. 
    /// </summary> 
    public HttpWebRequest Request 
    { 
     get 
     { 
      return _httpWebRequest; 
     } 
     set 
     { 
      _httpWebRequest = value; 
     } 
    } 

希望帮助!