I woud like to know how to enable the following scenario.
User clicks on a "download multiple images" button
In the click-handler, a collection of image IDs are requested for download:
http://domain.com/api/getimages/imageid1,imageid2,imageid3,imageid4
Web API controller returns JPEGs associated with the ImageIDs sequentially (rather than collectively). In this case, the images are dynamically generated from a database.
I prefer to use an async Task server side with HttpResponseMessage
Is this possible? Since I seek a performant response, I would like the response to be sequential rather than waiting for the assemblage of and return of the entire collection of images. So what I'm envisioning here is that when the image IDs are initially
requested, only the first image is pulled and returned in the response. And then subsequent responses containing each additional image are
pushed.
Keeping a pool of concurrently running HTTP requests would allow you do deal with that many files. The TCP connections would only be opened once, so the only overhead is the extra HTTP headers. However, you are going to have to re-invent the notion of
content-length headers if you try stuffing multiple images into a single response body.
I'm not exactly sure what performance problem you are trying to solve.
I've reached the conclusion that I should probably zip the collection of image files and return them in one go. The average size of an image file is ~3MB. Toward that end, I tried to use the DotNetZipLibrary. But I ran in to some issues outlined here: http://stackoverflow.com/questions/14573915/using-asp-net-web-api-how-can-a-controller-return-a-collection-of-streamed-imag
Asp.net is a request/response technology...the client makes a request, your .net code generates the response. One request, one response. In order to push down 50 images (ie send 50 responses) you will need to get the client to make 50 requests. Rather
than the click handler making one request for http://domain.com/api/getimages/imageid1,imageid2,imageid3,imageid4, it will have to make multiple requests to
So I actually tried do that with the following TypeScript code (which no doubt reflects my lack of expertise). But I ran into the issue of only getting one response because of the redirect.
private downloadFullSizeImages(displayer: DocumentDisplayer) {
for (var i = 0 ; i < displayer.viewers.length; i++) {
var imageID = $(displayer.viewers[i].elmt).parents('li').data('imageid');
var url: string = 'api/document/fullimage/' + imageID;
//document.location = <any>url;
//window.location.href = <any>url;
window.location.replace(url);
}
}
As you can see I tried three variations of fiddling with the location; but each version returned only the first image. Can you shed some light as to how I can fetch them all sequentially? Many thanks!
When you do a window.location.replace you are navigating away from the page so your code has stopped running. What you can do instead is create an IFRAME and make the src of the IFRAME your url, them add the IFRAME to the document (append it to a div, and
make sure its height and width are 1 so it can't be seen).
Marked as answer by calvindale on Jan 30, 2013 03:00 PM
calvindale
Member
16 Points
12 Posts
Is it possible to push multiple images sequentially down to the client in response to a single re...
Jan 28, 2013 06:50 PM|LINK
Greetings,
I woud like to know how to enable the following scenario.
Is this possible? Since I seek a performant response, I would like the response to be sequential rather than waiting for the assemblage of and return of the entire collection of images. So what I'm envisioning here is that when the image IDs are initially requested, only the first image is pulled and returned in the response. And then subsequent responses containing each additional image are pushed.
any ideas? thanks!
Darrel Mille...
Member
164 Points
55 Posts
Re: Is it possible to push multiple images sequentially down to the client in response to a singl...
Jan 29, 2013 01:30 PM|LINK
Why not issue the four requests in parallel? It is simple to do and should be very fast for the client.
calvindale
Member
16 Points
12 Posts
Re: Is it possible to push multiple images sequentially down to the client in response to a singl...
Jan 29, 2013 02:59 PM|LINK
Unlike my sample code, I want to enable requests of 30 to 50 files at a time.
Darrel Mille...
Member
164 Points
55 Posts
Re: Is it possible to push multiple images sequentially down to the client in response to a singl...
Jan 29, 2013 03:36 PM|LINK
Keeping a pool of concurrently running HTTP requests would allow you do deal with that many files. The TCP connections would only be opened once, so the only overhead is the extra HTTP headers. However, you are going to have to re-invent the notion of content-length headers if you try stuffing multiple images into a single response body.
I'm not exactly sure what performance problem you are trying to solve.
calvindale
Member
16 Points
12 Posts
Re: Is it possible to push multiple images sequentially down to the client in response to a singl...
Jan 29, 2013 03:54 PM|LINK
Thanks for your input Darrel.
I've reached the conclusion that I should probably zip the collection of image files and return them in one go. The average size of an image file is ~3MB. Toward that end, I tried to use the DotNetZipLibrary. But I ran in to some issues outlined here: http://stackoverflow.com/questions/14573915/using-asp-net-web-api-how-can-a-controller-return-a-collection-of-streamed-imag
AidyF
Star
9204 Points
1570 Posts
Re: Is it possible to push multiple images sequentially down to the client in response to a singl...
Jan 29, 2013 04:01 PM|LINK
Asp.net is a request/response technology...the client makes a request, your .net code generates the response. One request, one response. In order to push down 50 images (ie send 50 responses) you will need to get the client to make 50 requests. Rather than the click handler making one request for http://domain.com/api/getimages/imageid1,imageid2,imageid3,imageid4, it will have to make multiple requests to
http://domain.com/api/getimages/imageid1
http://domain.com/api/getimages/imageid2
http://domain.com/api/getimages/imageid3
http://domain.com/api/getimages/imagei4
and so on. If you need to send as many as 50 images then zipping them us and sending in one go is your best solution.
calvindale
Member
16 Points
12 Posts
Re: Is it possible to push multiple images sequentially down to the client in response to a singl...
Jan 29, 2013 04:38 PM|LINK
So I actually tried do that with the following TypeScript code (which no doubt reflects my lack of expertise). But I ran into the issue of only getting one response because of the redirect.
private downloadFullSizeImages(displayer: DocumentDisplayer) { for (var i = 0 ; i < displayer.viewers.length; i++) { var imageID = $(displayer.viewers[i].elmt).parents('li').data('imageid'); var url: string = 'api/document/fullimage/' + imageID; //document.location = <any>url; //window.location.href = <any>url; window.location.replace(url); } }As you can see I tried three variations of fiddling with the location; but each version returned only the first image. Can you shed some light as to how I can fetch them all sequentially? Many thanks!
AidyF
Star
9204 Points
1570 Posts
Re: Is it possible to push multiple images sequentially down to the client in response to a singl...
Jan 30, 2013 08:09 AM|LINK
When you do a window.location.replace you are navigating away from the page so your code has stopped running. What you can do instead is create an IFRAME and make the src of the IFRAME your url, them add the IFRAME to the document (append it to a div, and make sure its height and width are 1 so it can't be seen).
calvindale
Member
16 Points
12 Posts
Re: Is it possible to push multiple images sequentially down to the client in response to a singl...
Jan 30, 2013 03:11 PM|LINK
Thanks. I tried that approach using the following TypeScript. But it fails to return all requested images. Some are returned; other requests fail.
private downloadFullSizeImages(displayer: DocumentDisplayer) { if (!displayer || !displayer.viewers || displayer.viewers.length < 1) return; var urls : string[] = []; for (var i = 0 ; i < displayer.viewers.length; i++) { var imageID = $(displayer.viewers[i].elmt).parents('li').data('imageid'); var url: string = 'api/document/fullimage/' + imageID; urls.push(url); } displayer.download(urls); } private download(urls: string[]) { for (var i = 0; i < urls.length; i++) { var iframe = $('<iframe style="visibility: collapse;"></iframe>'); $('body').append(iframe); var content = iframe[0].contentDocument; var form = '<form action="' + urls[i] + '" method="GET"></form>'; content.write(form); $('form', content).submit(); setTimeout((function (iframe) { return function () { iframe.remove(); } })(iframe), 2000); } }