When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips

Sections:
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
XML Info
Information:
Feedback
Author an Article
ASP ASP.NET ASP FAQs Message Board Feedback

The 4 Guys Present: ASPFAQs.com

Jump to a FAQ
Enter FAQ #:
..or see our 10 Most Viewed FAQs.

4GuysFromRolla.com : ASP FAQS : The Nature of Things


Question:

How can I capture and use (i.e. save to disk, let the browser download) the output of one of my own ASP pages?


[Print this FAQ]

Answer: There are several viable solutions here, depending on your requirements and how fancy you want to be. First the simple solution: get your ASP page's output the same way you would get any other page's output, by HTTP request. Check out this FAQ for information on how to accomplish this:

How can I treat some other web page as data on my own site?

What this would essentially do is force your server to make an HTTP request to itself. This is inefficient, to say the least and, has potentially hazardous side effects (I've seen it crash PWS on Win9x machines). This is a possible but not recommended solution.

Instead, I recommend replacing the Response.Write statements you make to output the page with a custom object method and re-direct the output to wherever you want. The below VBScript 5.0 (or greater) class does just that, giving you 3 options: display (as usual), offer to the user as a download or save (by appending) to a file. (In order for this class you work you must have VBScript 5.0 or higher and all your page's output must be produced through Response.Write statements, which you replace with the .Write method of the CResponse class). (For more information on creating classes with VBScript, be sure to read: Using Classes within VBScript!)

Three steps to it's use:

1. Include the constants and class definition in your page.
2. Initialize the object as show in the usage example below.
3. Replace all Response.Write calls with objYourName.Write calls.

(To assist you in converting raw HTML into Response.Write produced HTML here is a utility that will enclose any string with whatever you want (including a preset Response.Write call: A client-side JavaScript string-encloser utility. There is also a link to a live demo at the conclusion of this article!)

<%
Response.Buffer = True
Const rcWriteToBrowser = 0
Const rcDownloadToBrowser = 1
Const rcSaveToFile = 3
Const ForAppending = 8

Class CResponse
    Dim rcWriteMode, strFileName, strHTML

' The FileName Property
    Public Property Let FileName(fn)
        strFileName = CStr(fn)
    End Property
    Public Property Get FileName
        FileName = strFileName
    End Property

' The WriteMode Property
    Public Property Let WriteMode(wm)
        rcWriteMode = Cint(wm)
    End Property
    Public Property Get WriteMode
        WriteMode = rcWriteMode
    End Property

    Private Sub Class_Initialize()
     strHTML = ""
    End Sub

    Private Sub Class_Terminate()
        Select Case rcWriteMode
            Case rcDownloadToBrowser
                Response.ContentType = "unknown/exe"
                Response.AddHeader "Content-Disposition","attachment;filename=" _
                    & Right(strFileName, Len(strFileName) - InStrRev(strFileName, "\"))
                Response.Write strHTML
                'Response.Write strFileName
            End Select
    End Sub

' The Write Method:
    Public Function Write(strInput)
        Select Case rcWriteMode
            Case rcWriteToBrowser
                Response.Write(strInput)
            Case rcDownloadToBrowser
                ' Collect HTML to use later:
                strHTML = strHTML & strInput
            Case rcSaveToFile
                Response.Write(strInput)
                Dim objFSO, objTS
                Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
                Set objTS = objFSO.OpenTextFile(strFileName, ForAppending, True)
                    objTS.WriteLine strInput
                objTS.Close
                Set objTS = Nothing
                Set objFSO = Nothing
        End Select
    End Function
End Class
%>


The first thing to note in the above source code are the three defined constants: rcWriteToBrowser, rcDownloadToBrowser, and rcSaveToFile. Next, note that the CResponse class has two properties: FileName and WriteMode. WriteMode indicates how the Response stream should be handled... should it be sent to the client's browser as streaming HTML, to the client's browser as a download file, or to a file on the Web server? WriteMode should be set to one of the three constant values defined at the top of the above source code. The FileName property indicates the physical path to squirt the Response object output to if the WriteMode property is set to rcSaveToFile.

The work of the class is handled in the Write method. Depending on the value of the WriteMode property, different steps are taken to squirt the Response stream to the correct outlet. If WriteMode is set to rcWriteToBrowser, the code is simply sent to the client with a standard Response.Write. If WriteMode is set to rcDownloadToBrowser, the output is appended to a string, strHTML, which is then squirted to the browser as a download file in the Terminate method of the class. Finally, if WriteMode is set to rcSaveToFile, a file is opened and has the current line appended to the end of the file. (A possible enhancement would be to simply build up a string and only write to the file once, in the Terminate method.)

Other possible enhancements for the CResponse class include:
-- Clear, Flush, and End methods to match those Response object methods (some changes would need to be made in the Write method to accomodate these additional method.
-- Error checking in the WriteMode Property Let statement, to ensure that the user assignes WriteMode one of the three allowable values.

Despite these potential areas for improvement, the CResponse class is a useful class as-is and illustrates some an important idea: how to redirect the output of the Response object. (Interestingly enough, with ASP.NET, it is quite easy to redirect the output of the Response object and you will not need to jump through such hoops as you do with classic ASP. (For more information on ASP.NET, be sure to check out the ASP.NET Article Index.)

Below is an exmaple of how this code could be used in an ASP page:

<%
'You would have to include the class in this file either
'explicitly or via a server-side include

Set objResponse = new CResponse
With objResponse
    .WriteMode = rcSaveToFile
    .FileName = "c:\test.html"

    ' Below is what used to be Response.Write calls:
    .Write("<html><head>")
    .Write("<title>This is my website!</title>")
    .Write("<body><p>Thanks for showing up!</p>") ' etc.
End With
%>

Note that when the user chooses to save a file, it is appended to the filename specified by the FileName property. To give this class a whirl, check out the live demo at:
http://www.aspfaqs.com/demos/CResponseTest.asp

(For more information on using the With statement, be sure to read: Using the With Block!)

Akhilesh recently sent in a link to a Microsoft HOWTO: How to Raise a "File Download" Box for a known MIME Type. Worth a read!

Happy Programming!


FAQ posted by Richard Lowe at 11/30/2000 7:45:48 AM to the The Nature of Things category. This FAQ has been viewed 75,978 times.

Do you have a FAQ you'd like to suggest? Suggestions? Comments? If so, send it in! Also, if you'd like to be a FAQ Admin (creating/editing FAQs), let me know! If you are looking for other FAQs, be sure to check out the 4Guys FAQ and Commonly Asked Messageboard Questions!

Most Viewed FAQs:

1.) How can I format numbers and date/times using ASP.NET? For example, I want to format a number as a currency. (761643 views)
2.) I am using Access and getting a 80004005 error (or a [Microsoft][ODBC Microsoft Access Driver] The Microsoft Jet database engine cannot open the file '(unknown)' error) when trying to open a connection! How can I fix this problem? (207777 views)
3.) How can I convert a Recordset into an array? Also, how can I convert an array into a Recordset? (202549 views)
4.) How can I quickly sort a VBScript array? (196039 views)
5.) How can I find out if a record already exists in a database? If it doesn't, I want to add it. (156019 views)
6.) How do I display data on a web page using arrays instead of Do...While...MoveNext...???... (152331 views)
7.) When I get a list of all files in a directory via the FileSystemObject, they aren't ordered in any reasonable way. How can I sort the files by name? Or by size? Or by date created? Or... (140381 views)
8.) For session variables to work, must the Web visitor have cookies enabled? (110162 views)
9.) Can I send emails without using CDONTS? (107083 views)
10.) How can I take the result of a SELECT...MULTIPLE or a group of same-named checkboxes and turn it into a query? That is, if the user selects 3 answers, how can I construct a query that looks for all 3? (106308 views)
Last computed at 9/17/2007 3:22:00 AM


ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article