views:

409

answers:

3

UPDATE:

  • Most of the answers given have just been some way of injecting the returned document into the html of the page, but this does not seem to be working. It might help if you could see what the aspx code is doing after all:

    Try
    
    
    
    RenderDocument = Session("docSelected")
    
    
    If Not String.IsNullOrEmpty(Request.QueryString("download")) Then
        asDownload = CBool(Request.QueryString("download"))
    End If
    
    
    If RenderDocument IsNot Nothing Then
    
    
        Dim docBytes() As Byte
        Dim docExtension As String = ""
        Dim docFileSize As Long
    
    
        GetBytesAndExtension(docBytes, docExtension, docFileSize)
    
    
        If docBytes IsNot Nothing Then
    
    
            Dim ms As New MemoryStream(docBytes)
    
    
            With ms
    
    
                Dim dataLengthToRead As Long = ms.Length
    
    
                Dim blocksize As Integer
                If dataLengthToRead >= 5000 Then
                    blocksize = 5000
                Else
                    blocksize = dataLengthToRead
                End If
    
    
                Dim buffer(dataLengthToRead) As Byte
    
    
                Response.Clear()
                Response.ClearContent()
                Response.ClearHeaders()
    
    
                Response.BufferOutput = True
    
    
                If asDownload = True Then
                    Response.AddHeader("Content-Disposition", "attachment; filename=" & RenderDocument.Name & "." & docExtension)
                Else
                    Response.AddHeader("Content-Disposition", "inline; filename=" & RenderDocument.Name & "." & docExtension)
                End If
    
    
                Response.AddHeader("Content-Length", docFileSize.ToString())
    
    
                Response.ContentType = "application/octet-stream"
    
    
                While dataLengthToRead > 0 And Response.IsClientConnected
                    Dim lengthRead As Integer = ms.Read(buffer, 0, blocksize)
                    Response.OutputStream.Write(buffer, 0, lengthRead)
                    dataLengthToRead = dataLengthToRead - lengthRead
                End While
    
    
                Response.Flush()
                Response.Close()
    
    
            End With
    
    
            Response.End()
    
    
        Else
    
    
            ResponseWithMessage("No Data")
    
    
        End If
    
    
    Else
    
    
        ResponseWithMessage("No Document")
    
    
    End If
    
    Catch ex As Exception ResponseWithMessage("ERROR: " & ex.Message) End Try
    • What is the significance of the return type of the $.post() function? In my code I use 'html', but actually it could be a file being returned.

===================

ORIGINAL QUESTION:

The scenario is I want to load a html page which will call a specific ASP.Net script, this script returns a document based on some data stored in the session. It's function is irrelevant, essentailly it returns the document as an http response, however it may return one of several error strings depending on what has occured.

The html page shows a loading gif image and then when the document or error message is returned it needs to handle these appropriately.

I can get the page to display the error messages without a problem, but I don't know how best to handle the document request being returned, at the moment it just opens a new window and calls the url again, but that is clunky and calls the whole document retrieval process again (synchronously!) which defeats the purpose of using a nice ajax style load.

This is my JQuery code:

$(document).ready(function(){
    $.post("displaydocument.aspx",null,function(data){

        if (data == 'No Document'){
            UpdateControls('No document has been specified to load');
        }

        if (data == 'No Data'){
            UpdateControls('No data was found for that document');
        }

        if (data.indexOf('ERROR',0) != -1) {
            UpdateControls(data);
        } 

        window.open("displaydocument.aspx","doc");
        window.close;

        }
    , "html");
});  

function UpdateControls(message){
    $("#txtInfo").html(message);
    $("#imgLoading").hide();
}

This is my html:

<div style="text-align: center; font-family: 'Trebuchet MS';">
    <img alt="loading" src="/images/loader64.gif" id="imgLoading" />
    <br />
    <span style="font-size: small" id="txtInfo">Document is loading...</span>
</div>

Your assistance is as always highly valued.

Thanks

+1  A: 

Open your window and set it's contents using JS instead of sending another request to the server.

Instead of

window.open("displaydocument.aspx","doc");

do something like:

var win = window.open();
win.document.write(data);

This will set the contents of the new window without retrieving the data again.

RaYell
Would that include all the response headers which are needed to tell the browser how to render the file?
Charlie
A: 

I would create a web/wcf service who's responsibility is to notify you if a certain file exists. You could then return a simple json string with either a success flag and if it fails a relevent error message.

This also saves the need to request the file twice and you would also gain a reusable service for future pages & projects. I know the response for the document should be cached however the above functionality allows you to give greater error message notification to the user.

$.getJson('fileExistsService.svc', { filename : someName }, function(data){

   if (data.success){
      //open document
      window.open("displaydocument.aspx","doc");
   }
   else {
     //display error to use
     //alert(data.errorMessage)
   }

})
redsquare
This does not really help. The user will be requesting a given document rather than the service telling me its available. Also a call to window.open() is sending a synchronous request to my displaydocument page so I still have to wait for the functionality on this page to complete.
Charlie
I read your q wrong I guess. You cant do what you want in the existing document especially as your changing the content type. You could use a modal dialog with an iframe.
redsquare
+1  A: 

Updated: I think the problem is that you are trying to do too much in one method. I would split it into two operations: check that the document is available and download the document. Have the method you call via POST (GET would work too since you aren't passing any data) do the existence check then create a link to a document handler URL that does the actual download. Add the link to the page and programmatically click it to invoke the download handler. The download handler would consist of your existing code and simply return an error page if invoked on a non-existent document. Note that the latter will not happen in normal operation, but could if someone bookmarked the downloaded document and it was removed.

Also, I'd be tempted to use JSON for the return value instead of HTML to make handling the error easier.

$(function() {
    $.get('checkfordocument.aspx',null,function(data) {
        if (!data.Success) {
           UpdateControls(data.Message);
        }
        else {
           UpdateControls('');
           $("<a href='"
                + data.Url
                + "' target='_blank' class='docLink'>"
                + "Click here if your document does not start downloading</a>")
             .appendTo('#txtInfo')
             .trigger('click');
    }
    ,'json');
});
tvanfosson
I did try this, but the browser does not render the document. It just displays a totally empty screen (IE 7).
Charlie
I updated my answer based on your changes.
tvanfosson
I evetually changed the methods to do something similar, so thanks (answer). I also liked the idea of the download link so I used that too. (+1)
Charlie