使用Silverlight 3构建文件上传应用。它可以上传几乎任何大小的文件 - 它可以使用4GB文件(取决于环境)。它上传了大量的文件,因此如果发生任何事情,可以从最新的块中恢复上传。
上传不起作用的情况是在上传大文件时在IE和Chrome中。他们似乎有记忆问题。在Firefox中,内存使用量是一个参差不齐的行 - 如果它正在读取文件的大块,上传它,丢弃它,然后再次在下一个块上重新开始就会出现这种情况。 IE和Chrome似乎坚持不懈。一旦可用的RAM用完,就会抛出OutOfMemoryException。
到目前为止,我已经尝试更改文件流和webrequest流大小,缓冲区等。我尝试过生成字节而不是从文件流中读取 - 同样的问题。我试过一次只写一个块,而不是我们现在使用的4kb缓冲区 - 同样的问题。
关于可能发生的事情的任何想法? IE和Chrome是不是垃圾收集来摆脱不需要的块?或者我应该使用一些http请求标头?关于如何确定内存使用位置的一些想法 - 在IE本身或Silverlight插件中?
答案 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之后,我也无法确定这里发生了什么。抱歉,我无法提供帮助。