1

I've been checking all over the place for an answer to this one but no luck.

I want a button or link that will open the "Save As" dialog box. Simple?

I know I can open the image in a new window/tab (as I'm doing now) and then use the right-click, save as method but as the people using this are not the sharpest knives in the box, so I want to make the download as simple as possible.

The code at the moment is:

<button class="downloadButton" type="submit" onClick="window.open('<%=(rsContent.Fields.Item("ContentImage").Value)%>')">Download Image</button>

but this loads the image into a new window/new tab.

Just for the record, the users are using Windows XP with Internet Explorer 8 so we can't use the download HTML5 event.

I don't mind if its JavaScript, JQuery or classic ASP.

Thanks in advance for the help.

Pb

UPDATE

Using the MDN code Lankymart posted, I tried as-is and it worked (for the open/download of an Excel document), however, I tried changing parts to download images and it didn't work.

Here is the Classic ASP code:

<%
Dim rsImage__imageID
rsImage__imageID = "1"
If (Request.QueryString("imageID")  <> "") Then 
  rsImage__imageID = Request.QueryString("imageID") 
End If
%>
<%
Dim rsImage
Dim rsImage_cmd
Dim rsImage_numRows

Set rsImage_cmd = Server.CreateObject ("ADODB.Command")
rsImage_cmd.ActiveConnection = MM_ENG_STRING
rsImage_cmd.CommandText = "SELECT ContentID, ContentImage, DisplayImage FROM tblContent WHERE ContentImage = ?" 
rsImage_cmd.Prepared = true
rsImage_cmd.Parameters.Append rsImage_cmd.CreateParameter("param1", 5, 1, -1, rsImage__imageID) ' adDouble

Set rsImage = rsImage_cmd.Execute
rsImage_numRows = 0
%>

and the (badly) altered MDN code:

<%
'Set the content type to the specific type that you are sending.
Response.ContentType = "image/JPEG"

Const adTypeBinary = 1
Dim strImageFile

strImageFile = (rsImage.Fields.Item("ContentImage").Value) 'This is the path and name of the file on disk. 

Set objStream = Server.CreateObject("ADODB.Stream")
objStream.Open
objStream.Type = adTypeBinary
objStream.LoadFromFile strImageFile

Response.BinaryWrite objStream.Read

objStream.Close
Set objStream = Nothing
%>

I call it using:

<button class="downloadButton" type="submit" onClick="window.location.href='image-download.asp?imageID=<%=(rsContent.Fields.Item("ContentID").Value)%>';">Download Image</button>

The error it produces is:

The image “http://localhost:85/admin/english/image-download.…p?imageID=5” cannot be displayed because it contains errors.

The page code is:

<html>

    <head>
        <meta name="viewport" content="width=device-width; height=device-height;"></meta>
        <link rel="stylesheet" href="resource://gre/res/ImageDocument.css"></link>
        <link rel="stylesheet" href="resource://gre/res/TopLevelImageDocument.css"></link>
        <link rel="stylesheet" href="chrome://global/skin/media/TopLevelImageDocument.css"></link>
        <title>

            image-download.asp (JPEG Image)

        </title>
    </head>
    <body>
        <img src="http://localhost:85/admin/english/image-download.asp?imageID=5" alt="The image “http://localhost:85/admin/english/image-download.…p?imageID=5” cannot be displayed because it contains errors." title=""></img>
    </body>

</html>
Community
  • 1
  • 1
  • Can't mark as duplicate - [JavaScript: Prompting user to save file using a 'Save-as' dialog?](http://stackoverflow.com/questions/19679842/javascript-prompting-user-to-save-file-using-a-save-as-dialog) but you should look at this question. – user692942 Mar 24 '14 at 14:23
  • Since my comment I've added an answer as you might not be able to do it with javascript, but you can kinda "fake" it with a image processing page. – user692942 Mar 24 '14 at 15:07
  • Now that you've shown the code you have tried what error do you get? Could you also include that? – user692942 Mar 26 '14 at 13:06
  • Updated question with error output. –  Mar 26 '14 at 14:36
  • From your very generic error it is unclear where your code is failing `cannot be displayed because it contains errors` is not going to help you debug your issue. Do you have your `500-100.asp` setup for handling `500.100 Internal Server Errors` in IIS?, without it no errors you receive will be meaningful. – user692942 Mar 27 '14 at 12:48
  • I had no idea about 500.100.asp. I'll sort it now. Back soon. –  Mar 27 '14 at 19:54
  • If you need help setting up `500-100.asp` look here [HTTP 500 error message displays instead of ASP error message from 500-100.asp](http://support.microsoft.com/kb/261200/en) and [500 Vs 500.100 Error in Classic ASP](http://stackoverflow.com/a/9407559/692942). – user692942 Mar 28 '14 at 09:35
  • I found both of these links in my hunt but as I know enough about IIS to be dangerous, I can't quite figure out how to make it work in IIS 7. Still working on it. Thanks for the links though. –  Mar 28 '14 at 12:41
  • In IIS 7 if you add a virtual directory to your site called `IISHelp` and point the location to (this is a guess) `%systemdrive%\inetpub\custerr\` (`` normally will be `en-US`) once you have done this go to Custom Error Pages and modify 500.100 to use URL `/IISHelp/500-100.asp`. – user692942 Mar 28 '14 at 13:07
  • Can I add this to the 'Default Web Site' so that it's available across all virtual sites? The reason I ask, is because I have a number of virtual sites on my computer. –  Mar 28 '14 at 13:51
  • When you say virtual sites do you mean you run all your sites inside Default Website as virtual directories? If yes then yeah set your Custom Error Page for 500.100 at the Default Website level. – user692942 Mar 28 '14 at 13:55
  • No, they all run outside the default. I presume that means I need to add a virtual folder to each virtual site? –  Mar 28 '14 at 13:57
  • Yes, but there may be a way to export the and import the virtual directory to each site. I'd try it on the one we are trying to debug first at least and go from there. – user692942 Mar 28 '14 at 14:05
  • OK, installed in both just to be on the safe side and I'm still getting the same error message. There seems to me no more information. I'm using Firefox so I'll switch to IE (I have friendly HTTP messages turned off). –  Mar 28 '14 at 14:08
  • In the ASP section under Debugging Properties you may also need to have `Send Errors to Browser` set to `true`. Also checkout [This SO answer](http://stackoverflow.com/a/5474932/692942). – user692942 Mar 28 '14 at 14:18
  • Just tried IE (version 11) and I got a message bar stating "Do you want to open or save **image-download_asp?imageID=8** (364 bytes) from **localhost**?" along with the "Open", "Save" and "Cancel" options. If I choose save, the "Save As" window opens. If I click the "Save" button in the window with the default File Name, nothing happens. If I change the name and add the relevant extension, the window closes and a message appears in the parent window stating "image.jpg couldn't be downloaded." along with the buttons "Retry", "Cancel" and "View downloads". –  Mar 28 '14 at 14:20
  • `Send Errors to Browser` I set when I installed IIS. –  Mar 28 '14 at 14:21
  • You might find it useful to debug your responses using [Fiddler](http://www.telerik.com/fiddler) it acts as a proxy and captures all web traffic, useful for seeing the raw response the server is sending back. – user692942 Mar 28 '14 at 14:45
  • How did you get on, did you get any further using Fiddler? – user692942 Apr 03 '14 at 09:04
  • Sorry for taking so long to get back to this question but some fool put work my way. I've downloaded [Fiddler](http://www.telerik.com/fiddler) and installed the Firefox addon and it doesn't seem to be reporting anything different but that's probably because I have no idea what I'm doing. I'll keep trying though. –  Apr 12 '14 at 11:37

2 Answers2

2

You can create a button that point to a link returning the image as a file and it will show the save option automatically instead of navigate to another page.

On the server side, specify the mime type as application/octect-stream

Sérgio S. Filho
  • 364
  • 1
  • 4
  • 13
2

Update - Related to comments in the question

You may also find you need to include

Response.AddHeader("Content-Length", LenB(yourbinary))

To stop some browsers from failing to validate the payload. Also it's important the the ContentType matches what is sent if you are unsure use

Response.Content = "application/octet-stream"

There is no way to initiate the Save As Dialog from the browser via javascript but you can fake the browser into displaying the Save As dialog by setting the attachment value in the Content-Disposition HTTP header.

The way I've tackled this is use a ASP page to generate the image (via COM component, ADODB.Stream, database blob etc) that way you can use;

Response.AddHeader("Content-Disposition", "attachment;filename=myimage.jpg")

This will force the image to be saved rather than displayed inline. So with a script like this you can pass one querystring value to it to display inline (when viewing the image) and one to force it as an attachment which will force the Save As dialog (browser behaviour may be slightly different).

Streaming to the Browser

Using the ADODB.Stream object to output files to the browser.

In the past I've initiated the Save As dialog using javascript (but there is nothing stopping you using a HTML anchor tag to do the same thing without any javascript);

/* 
passing myimageid is a way of identifying the image to return 
be it a database or file system lookup.
*/
window.location.href = "/myimage.asp?id=myimageid&display=attachment";

Because the response comes back as an attachment the location is never actually changed and the Save As dialog is displayed immediately with the name of the file passed from the Content-Disposition HTTP header in the file name box.

Community
  • 1
  • 1
user692942
  • 16,398
  • 7
  • 76
  • 175
  • Thanks for this. Your answer is well above my head but I'm trying, so, just a couple questions. 1). The site is on a hosting site, would this still be OK? 2). MDN states "After a header has been added, it cannot be removed." Will this affect ALL images as some images, not on the admin site, are part of a lightbox? –  Mar 24 '14 at 18:26
  • @MartySmartyPants You don't change the headers of the source images what you do is build a ASP page that outputs as `Content-Type: image/jpeg` for example and you feed your image into the ASP page using something like `ADODB.Stream` object. That link should help. – user692942 Mar 24 '14 at 18:33
  • Sorry, I should have put the MDN statement in context. It was referring to HTTP Headers not images. –  Mar 24 '14 at 19:14
  • @MartySmartyPants I understood. What I was trying to say is your HTTP headers are not written until the response buffer is flushed. The usual approach to this is 1. `Response.ContentType = ""` 2. Pull your file / db blob into a `ADODB.Stream` 3. Output the response buffer using `Response.BinaryWrite(yourbinary)`. You can add your headers at any step before step 3. once you do that your headers are written and cannot be altered. – user692942 Mar 24 '14 at 19:28
  • @MartySmartyPants Added a link to a simple example of how to use `ADODB.Stream` to output a file to the browser - [How To Use the ADODB.Stream Object to Send Binary Files to the Browser through ASP](http://support.microsoft.com/kb/276488). – user692942 Mar 24 '14 at 20:56
  • I'm sorry but this really is over my head. I've used the examples you've given (especially the MDN, which worked providing I used the code 'as-is') but when I tried to make changes to download images, the wheels fell off. –  Mar 26 '14 at 10:43
  • @MartySmartyPants Can you [update your question](http://stackoverflow.com/posts/22612009/edit) with what code you have tried and I'll help best I can. – user692942 Mar 26 '14 at 10:46