Я пытаюсь реализовать загрузчик нескольких файлов в Silverlight 4. Элемент управления Silverlight содержит только одну кнопку. при щелчке по нему отображается OpenFileDialog, и они могут выбрать несколько файлов. Как только они закрывают диалог, объект FileInfo для всех выбранных файлов добавляется в список. затем в моей веб-форме у меня есть кнопка javascript, которая при нажатии вызывает метод в элементе управления silverlight для циклического перемещения по списку и загрузки файлов. этот метод возвращает строку, содержащую виртуальные пути ко всем загруженным файлам, разделенные точкой с запятой. Затем я могу использовать эту строку, чтобы добавить пути ко всем изображениям в базу данных в коде c # позади.
файл загружается путем вызова метода OpenRead () объекта FileInfo, чтобы получить поток, содержащий байты файла, создания объекта WebClient и вызова метода OpenWriteAsync, передавая URI обработчика HTTP на моем веб-сайте. событие 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 (если вы можете, ПОЖАЛУЙСТА, скажите мне, как :-)).
Я работаю над этим уже 2 дня, и нигде не получаю, поэтому любая помощь будет высоко ценится