Silverlight文件上传内存问题

时间:2010-01-21 02:06:38

标签: silverlight file memory upload

使用Silverlight 3构建文件上传应用。它可以上传几乎任何大小的文件 - 它可以使用4GB文件(取决于环境)。它上传了大量的文件,因此如果发生任何事情,可以从最新的块中恢复上传。

上传不起作用的情况是在上传大文件时在IE和Chrome中。他们似乎有记忆问题。在Firefox中,内存使用量是一个参差不齐的行 - 如果它正在读取文件的大块,上传它,丢弃它,然后再次在下一个块上重新开始就会出现这种情况。 IE和Chrome似乎坚持不懈。一旦可用的RAM用完,就会抛出OutOfMemoryException。

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

关于可能发生的事情的任何想法? IE和Chrome是不是垃圾收集来摆脱不需要的块?或者我应该使用一些http请求标头?关于如何确定内存使用位置的一些想法 - 在IE本身或Silverlight插件中?

2 个答案:

答案 0 :(得分: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;
        }
    }

希望有所帮助!

答案 1 :(得分:0)

即使在升级到Silverlight 4之后,我也无法确定这里发生了什么。抱歉,我无法提供帮助。