我正在尝试在Silverlight 4中实现多文件上传器。该Silverlight控件仅包含一个按钮。当单击此按钮时,会显示OpenFileDialog并可以选择多个文件。一旦关闭对话框,所选文件的FileInfo对象将添加到列表中。然后,在我的Web表单中,我有一个JavaScript按钮,单击它将调用Silverlight控件中的方法来循环遍历列表并上传文件。此方法返回一个包含所有已上传文件虚拟路径的字符串,用分号分隔。然后,我可以使用此字符串将所有图像路径添加到C#代码后端的数据库中。
通过调用FileInfo对象的OpenRead()方法获取包含文件字节的流,并创建WebClient对象并调用OpenWriteAsync方法,传递我的网站中HTTP处理程序的URI来上传文件。 Web客户端的OpenWriteCompleted事件被设置为将FileInfo对象的流写入其输出流。
HTTP处理程序从请求流中读取字节,并使用FileStream将它们保存到文件中。
以下是Silverlight控件的代码:
我遇到的问题是HTTP处理程序只有一半的时间实际上创建图像文件,有时它只写入文件的一部分字节,因此会得到损坏的图像文件。似乎没有任何异常被抛出,并且似乎无法预测何时会成功和何时会失败。我最初的想法是HTTP处理程序无法同时处理这么多请求并且崩溃了。如果可以的话,我会同步上传每个图像,但在Silverlight中无法这样做(如果可以,请告诉我如何 :-))。
我已经全力工作了两天,但还没有取得任何进展,所以非常感谢任何帮助。
通过调用FileInfo对象的OpenRead()方法获取包含文件字节的流,并创建WebClient对象并调用OpenWriteAsync方法,传递我的网站中HTTP处理程序的URI来上传文件。 Web客户端的OpenWriteCompleted事件被设置为将FileInfo对象的流写入其输出流。
HTTP处理程序从请求流中读取字节,并使用FileStream将它们保存到文件中。
以下是Silverlight控件的代码:
public partial class MainPage : UserControl
{
private List<FileInfo> files = new List<FileInfo>();
private String handlerUrl;
private String imageBin;
public MainPage(string handlerUrl, string imageBin)
{
InitializeComponent();
this.handlerUrl = handlerUrl;
this.imageBin = imageBin;
if (!(this.imageBin.EndsWith("/")))
this.imageBin += "/";
//register control as scriptable object to allow methods to be called from javascript
HtmlPage.RegisterScriptableObject("SilverlightCode", this);
}
private void btnBrowse_Click(object sender, RoutedEventArgs e)
{
files.Clear();
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
bool? showDialog = ofd.ShowDialog();
if ((showDialog != null) && (showDialog.Value))
{
try
{
foreach (FileInfo fi in ofd.Files)
{
//check file is valid image file
BitmapImage source = new BitmapImage();
source.SetSource(fi.OpenRead());
files.Add(fi);
}
}
catch
{
txtBrowse.Text = "Invalid image file selected.";
files.Clear();
return;
}
}
if (files.Count == 1)
txtBrowse.Text = "1 image selected.";
else
txtBrowse.Text = files.Count.ToString() + " images selected.";
}
[ScriptableMember]
public string UploadImages()
{
try
{
String s = "";
String now = DateTime.Now.ToString("yyyyMMddHHmmss");
for (int i = 0; i < files.Count; i++)
{
String filename = imageBin + now + i.ToString("00000") + files[i].Extension;
s += filename + "; ";
UploadImage(files[i], filename, i);
}
return s.Trim();
}
catch
{
return "";
}
}
private void UploadImage(FileInfo imageFile, String uploadImageVirtualPath, int index)
{
UriBuilder ub = new UriBuilder(handlerUrl);
ub.Query = String.Format("filename={0}", uploadImageVirtualPath);
Stream stream = imageFile.OpenRead();
WebClient client = new WebClient();
client.OpenWriteCompleted += (sender, e) =>
{
PushData(stream, e.Result);
e.Result.Close();
stream.Close();
};
client.OpenWriteAsync(ub.Uri);
}
private static void PushData(Stream input, Stream output)
{
byte[] buffer = new byte[input.Length];
input.Read(buffer, 0, buffer.Length);
output.Write(buffer, 0, buffer.Length);
}
}
这里是HTTP处理程序的代码:
public class ImagesHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//process request
string filename = context.Request.QueryString["filename"].ToString();
using (FileStream fs = File.Create(context.Server.MapPath(filename)))
{
SaveFile(context.Request.InputStream, fs);
}
}
private void SaveFile(Stream stream, FileStream fs)
{
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, buffer.Length);
}
public bool IsReusable
{
get
{
return true;
}
}
}
我遇到的问题是HTTP处理程序只有一半的时间实际上创建图像文件,有时它只写入文件的一部分字节,因此会得到损坏的图像文件。似乎没有任何异常被抛出,并且似乎无法预测何时会成功和何时会失败。我最初的想法是HTTP处理程序无法同时处理这么多请求并且崩溃了。如果可以的话,我会同步上传每个图像,但在Silverlight中无法这样做(如果可以,请告诉我如何 :-))。
我已经全力工作了两天,但还没有取得任何进展,所以非常感谢任何帮助。