I have problem when using the upload control. Please help.
1) I try to resize the image in the before uploading to the server, but it does not work. It loads the original image.
private void radUpload1_FileUploadStarting(object sender, FileUploadStartingEventArgs e)
{
RadUploadSelectedFile file = e.SelectedFile as RadUploadSelectedFile;
WriteableBitmap wb;
using (Stream stream = file.File.OpenRead())
{
wb = ResizeImage(stream, 300); //resize the image to 300 pix
}
using (Stream Source = GetSource(wb))
{
// The GetSource function will return the small Stream from the new resize image. This is working
// upload the resized image instead the original image.
// This does not work. It loads the original image but not the new image.
e.NewFileStream = Source;
}
}
2) When I try to upload more than 1 image. When start to load the second, it will throw out "Invalid cross-thread access."
private WriteableBitmap ResizeImage(Stream stream, double targetSize)
{
// This is the line that throw the error when the second image start to load.
BitmapImage bmp = new BitmapImage();
bmp.SetSource(stream);
Image img = new Image();
img.Source = bmp;
double scaleX = 1;
double scaleY = 1;
if (bmp.PixelHeight > targetSize)
scaleY = targetSize / bmp.PixelHeight;
if (bmp.PixelWidth > targetSize)
scaleX = targetSize / bmp.PixelWidth;
double scale = Math.Min(scaleY, scaleX);
int newWidth = Convert.ToInt32(bmp.PixelWidth * scale);
int newHeight = Convert.ToInt32(bmp.PixelHeight * scale);
WriteableBitmap result = new WriteableBitmap(newWidth, newHeight);
result.Render(img, new ScaleTransform() { ScaleX = scale, ScaleY = scale });
result.Invalidate();
return result;
}
Thank you.
16 Answers, 1 is accepted
Can you please take a look at the project I attached to the support thread you sent. Thank you in advance.
Greetings,
Tina Stancheva
the Telerik team
![](/forums/images/avatarimages/default.gif)
Can you post your project please? I got the very same issue.
Thank you
In order to resize the uploaded images on the clent-side you can use the approach described here.
I also attached the sample project. Hope it helps.
Best wishes,
Tina Stancheva
the Telerik team
![](/forums/images/avatarimages/default.gif)
Very interesting article.
But HOW I can use it in the RadUpload events?
Thank you for your precious time.
In the previously attached sample (348506-uploadsample.zip) the FileUploadStarting event is handled to get the stream of each SelectedFile in order to resize it.
The ResizeImage method actually resizes the SelectedFile using its source and returning the result as a WriteableBitmap. Once you have the resized WriteableBitmap object, you can pass it to the server using the e.NewFileStream property. Here you can either go with the approach illustrated in the attached project - creating a buffer, or you can simply implement the following:
private
void
myUpload_FileUploadStarting(
object
sender, FileUploadStartingEventArgs e)
{
RadUploadSelectedFile file = e.SelectedFile
as
RadUploadSelectedFile;
WriteableBitmap wb;
using
(Stream stream = file.File.OpenRead())
{
wb = ResizeImage(stream, 300);
//resize the image to 300 pix
}
e.NewFileStream = JpgEncoder.Encode(wb, 50);
}
All the best,
Tina Stancheva
the Telerik team
![](/forums/images/avatarimages/default.gif)
Thank you a lot for the project. But I dont see anything about multiple files.
Can you explain more about the situation when I upload more that 1 file? I suppose it's use some kind of foreach...
Wait for your answer.
Bye bye
Please accept my apology for the delayed response.
The FileUploadStarting event occurs before a file starts uploading therefore it occurs for each selected file. And since the resizing logic is entirely implemented in FileUploadStarting event handler, you shouldn't have any issues implementing it for multiple files.
For example if 3 image files are selected for upload in the above example - Image1.png, Image2.png, Image3.png, the FileUploadStarting event will be raised 3 times for each image in the order the images are displayed in the RadUpload control (alphabetically) and the FileUploadStartingEventArgs e object will hold the image file that is about to be uploaded and will modify its size accordingly.
Here you can find more info about the RadUpload events. I hope this info helps but please let me know if you need more or if I am missing something.
Greetings,
Tina Stancheva
the Telerik team
![](/forums/images/avatarimages/default.gif)
No problem about the delay. You help me a lot.
But, when I try to upload 3 or 4 files (see iimage), I got this error "Invalid cross-thread access" at
BitmapImage bmp = new BitmapImage();
This seem related to thread. So, what's I can do to manage it? I read something about this "problem" (http://stackoverflow.com/questions/1924408/invalid-cross-thread-access-issue) :Also, BitmapImages have to be instantiated on the UI thread. This is because it uses DependencyProperties, which can only be used on the UI thread. I have tried instantiating BitmapImages on separate threads and it just doesn't work. You could try to use some other means to store images in memory. For example, when you download the image, store it in a MemoryStream. Then a BitmapImage on the UI thread can set its source to the MemoryStream.
private void RadUploadPhotosEspaceClos_FileUploadStarting(object sender, Telerik.Windows.Controls.FileUploadStartingEventArgs e)
{
RadUploadSelectedFile file = e.SelectedFile as RadUploadSelectedFile;
WriteableBitmap wb;
using (Stream stream = file.File.OpenRead())
{
wb = ResizeImage(stream, 500); //resize the image to 300 pix
}
byte[] buffer;
using (Stream Source = JpgEncoder.Encode(wb, 80))
{
int bufferSize = Convert.ToInt32(Source.Length);
buffer = new byte[bufferSize];
Source.Read(buffer, 0, bufferSize);
}
//NOTE: use the buffer to show the image...
e.NewFileStream = new MemoryStream(buffer);
}
private WriteableBitmap ResizeImage(Stream stream, double targetSize)
{
BitmapImage bmp = new BitmapImage();
bmp.SetSource(stream);
System.Windows.Controls.Image img = new System.Windows.Controls.Image();
img.Source = bmp;
double scaleX = 1;
double scaleY = 1;
if (bmp.PixelHeight > targetSize)
scaleY = targetSize / bmp.PixelHeight;
if (bmp.PixelWidth > targetSize)
scaleX = targetSize / bmp.PixelWidth;
double scale = Math.Min(scaleY, scaleX);
int newWidth = Convert.ToInt32(bmp.PixelWidth * scale);
int newHeight = Convert.ToInt32(bmp.PixelHeight * scale);
WriteableBitmap result = new WriteableBitmap(newWidth, newHeight);
result.Render(img, new ScaleTransform() { ScaleX = scale, ScaleY = scale });
result.Invalidate();
return result;
}
Please try using the Dispatcher.BeginInvoke() method inside the FileUploadStarting event. This will ensure that you are always on the main (UI) thread and you should not be getting this exception. The source of this issue is that the server side of the RadUpload is raising this event and it is on another thread. We are currenctly working on resolving this trying to prevent any concurrency or timing issues that may appear.
Sincerely yours,
Alex Fidanov
the Telerik team
![](/forums/images/avatarimages/default.gif)
A big thank you for your answer. But I have already try this code (see below) and file are transfered but the size are not changed (see jpg attached file). Do you see something wrong in my code?
private void RadUploadPhotos_FileUploadStarting(object sender, Telerik.Windows.Controls.FileUploadStartingEventArgs e)
{
RadUploadSelectedFile file = e.SelectedFile as RadUploadSelectedFile;
WriteableBitmap wb;
Deployment.Current.Dispatcher.BeginInvoke ( () =>{
using (Stream stream = file.File.OpenRead())
{
wb = ResizeImage(stream, 500); //resize the image to 300 pix
}
byte[] buffer;
using (Stream Source = JpgEncoder.Encode(wb, 80))
{
int bufferSize = Convert.ToInt32(Source.Length);
buffer = new byte[bufferSize];
Source.Read(buffer, 0, bufferSize);
}
e.NewFileStream = new MemoryStream(buffer);
});
}
private WriteableBitmap ResizeImage(Stream stream, double targetSize)
{
BitmapImage bmp = new BitmapImage();
bmp.SetSource(stream);
System.Windows.Controls.Image img = new System.Windows.Controls.Image();
img.Source = bmp;
double scaleX = 1;
double scaleY = 1;
if (bmp.PixelHeight > targetSize)
scaleY = targetSize / bmp.PixelHeight;
if (bmp.PixelWidth > targetSize)
scaleX = targetSize / bmp.PixelWidth;
double scale = Math.Min(scaleY, scaleX);
int newWidth = Convert.ToInt32(bmp.PixelWidth * scale);
int newHeight = Convert.ToInt32(bmp.PixelHeight * scale);
WriteableBitmap result = new WriteableBitmap(newWidth, newHeight);
result.Render(img, new ScaleTransform() { ScaleX = scale, ScaleY = scale });
result.Invalidate();
return result;
}
This looks like a timing issue when dispatching the code inside the event handler. I have logged this ("RadUpload: Concurrency issue when using a Dispatcher inside the FileUploadStarting event") as an issue in our PITS system and you can check its progress from here. Your Telerik points were also updated.
Sincerely yours,
Alex Fidanov
the Telerik team
![](/forums/images/avatarimages/default.gif)
I have the same issue. I get a cross-thread exception when uploading multiple flies.
For each file, when the file uploading event occurs, i try and set some file parameters from my ViewModel. I found that when i get to the File uploading event the 2nd time, i get a cross thread exception when trying to call a method on my ViewModel. In fact, i can't even cast my ViewModel (it's an interface reference in the view, using prism) to my actual concrete ViewModel class, i get the cross-thread exception.
So i tried the Dispatcher.BeginInvoke(). The problem with that is it runs async and my method returns before the Dispatcher has time to set the event args for the file parameters. So i basically need to "wait" for the dispatcher call to finish.
Here is how i worked around the issue:
private
int
originalThreadId;
private
AutoResetEvent _waitHandler =
new
AutoResetEvent(
false
);
private
void
RadUpload1_FileUploadStarting(
object
sender, FileUploadStartingEventArgs e)
{
if
(originalThreadId == 0)
{
originalThreadId = Thread.CurrentThread.ManagedThreadId;
}
var isOriginalThread = (originalThreadId == Thread.CurrentThread.ManagedThreadId);
if
(!isOriginalThread)
{
Dispatcher.BeginInvoke(() =>;
{
Debug.WriteLine(
"Starting RadUpload1_FileUploadingStarting.BeginInvoke.GetDocumentModelForUpload"
);
_waitHandler.Reset();
//Call this method to make sure the _waitHandler is indeed in a wait state.
ViewModel.GetDocumentModelForUpload(e.FileParameters, e.SelectedFile.Name);
_waitHandler.Set();
//Signal _waitHandler to continue on
});
}
else
{
Debug.WriteLine(
"Starting RadUpload1_FileUploadingStarting.GetDocumentModelForUpload"
);
ViewModel.GetDocumentModelForUpload(e.FileParameters, e.SelectedFile.Name);
}
if
(!isOriginalThread)
{
//Only call this if we are not on the original thread.
_waitHandler.WaitOne();
}
}
![](/forums/images/avatarimages/default.gif)
Please accept our apology for this inconvenience, unfortunately this issue hasn't been addressed yet. I am not sure what is your scenario and why you use the FileUploadStarting event, but if you can modify your implementation not to use the handler of this event, that should get over the exception.
Kind regards,
Tina Stancheva
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
![](/forums/images/avatarimages/21b5f314-1b6a-4b44-8af6-cde1967eed1edave_hs.jpg)
I'm also looking to resize images (for thumbnails) before uploading.
Are the methods described in this post still the suggested methods now that we're using Silverlight 5?
I've got one of the samples wired up but I'm getting corrupted files in the end... so, my hope is that there's a new method in place. Ideally, it would be a function built into SL5.
Anyway, please let me know and thanks!
~ Dave
We are not aware of any other approaches in Silverlight 5 for resizing images. And the approach described in the thread works as expected on our side so I'm not sure what might be corrupting the files on your side. If you'd like, you can send over a sample solution demonstrating the issue so that we can take a closer look at it.
Regards,
Tina Stancheva
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.