Online documentation - Websydian v6.5 |
The BinaryPageGenerator pattern is used when you want to let the user download a file from the application to his PC/browser.
The file can either be a static file or it can be a file that you have generated at an earlier step in the processing of the user request.
The BinaryPageGenerator reads the file and streams the content unaltered to the browser after setting HTTP-headers that describe the content.
The file name of the file to download.
The full path to the folder containing the file to download. This must end with a path separator ("\" or "/", depending on the variant).
The DocumentPath and DocumentName are concatenated to create the location of the file to download.
The DocumentName will be used as the name of the file in the default content type header set by the system.
The developer must specify the HTTP-headers, which is sent before the file-content.
The HTTP-headers describe the content of the file and how the browser should handle the file.
The pattern does not have any way to determine the content of the file that is being handled, so the developer must ensure that the correct headers are sent.
The unaltered BinaryPageGenerator sends three headers (described below). You can add additional headers if needed.
The Content-Type entity-header field indicates the media type of the entity-body sent to the recipient. This header makes it possible for the browser to determine which application it can use to handle the file-content (based on the users system preferences/browser settings).
The Content-disposition header is used by the browser to determine whether the file content should be handled as content that should be shown right away as part of the web site being loaded (Content-disposition:inline) or whether file should be handled as a downloaded file that the user can choose to either save or display (Content-disposition:attachment).
For Content-disposition:attachment, you can also specify the filename the user will be informed about - this results in the format:
Content-disposition:attachement;filename="myfilename".
As far as can be determined, no current browser versions use this header.
This section only describes how headers are specified for the DWA variants of Websydian.
The headers are specified in the subroutine "Send headers" in the BinaryPageGenerator.
If you need to add further headers it is vital that it is done in this subroutine, as the headers must be set after the connection is initialized, but before the file content is streamed.
You can add additional headers by setting the values for the local fields Local<HeaderName> and Local<HeaderValue> followed by a Go Sub write document line statement.
If you want to change the values of the three headers the standard BinaryPageGenerator already specifies, you must undefine the entire subroutine, copy the content of the subroutine and set the headers to the values described above.
To be able to send the correct information in the Content-type header, it is necessary to know the media type that corresponds to the file content.
Note that MS-Office changed the document formats in version 2007. This means that each MS-Office program has two separate formats, which each has it's own media type.
For example, Word documents have a version (.doc), which corresponds to the media type application/msword and a version (.docx), which corresponds to the media type: application/vnd.openxmlformats-officedocument.wordprocessingml.document.
The content of the file determines which media type you must specify.
Note that no matter the content will be shown by the application the user has specified for the media type you specify in the headers. If the user has selected a program that can't open the media an error will occur. If the user hasn't selected an application for the specified media type, he will be prompted to select one.
The way the different browsers handle the Content-Type and Content-disposition headers are not same.
When using the BinaryPageGenerator, it is even more important than usual to test all combinations of browsers, browser versions, and file content that you want to support. Even for a specific browser the handling of a specifc content type can be different in different versions of the borwser.
Note that these examples are DWA-specific.
If you use the PC webserver or iSeries webserver variants, the headers are set in a different manner.
The media type for pdf is: application/pdf
When the default behavior is to show the file in the browser, the Content-disposition should be set to inline.
Define the BinaryPageGenerator by specifying the triple:
Source Object | Verb | Target Object |
---|---|---|
MyBinaryPageGenerator | is a FNC | BinaryPageGenerator |
Create two messages that will be used to create the Content-type and Content-disposition header values
Source Object | Verb | Target Object |
---|---|---|
MyBinaryPageGenerator | message MSG | ContentType |
MyBinaryPageGenerator | message MSG | ContentDisposition |
Specify the following literal values:
MyBinaryPageGenerator.ContentType: application/pdf
MyBinaryPageGenerator.ContentDisposition: inline
In the Post Point "Start Send Headers enter the following code:
+If Variant: WsyBase/DWA - Windows
+Else
Call WsyBase/WpkaSetResponseCharset
Map with:
WsyBase<ConnectionPointer>
ResponseCharset<*BINARY>
Set Document<TypeInfo> = <TypeInfo.Specific>
Set Document<DocumentAction> = <DocumentAction.Open>
Set Local<HeaderName> = <HeaderName.Content-type>
Format Message Message: MyBinaryPageGenerator.ContentType, Local<HeaderValue>
Go Sub Write document line
Set Local<HeaderName> = <HeaderName.Content-disposition>
Format Message Message: MyBinaryPageGenerator.ContentDisposition, Local<HeaderValue>
Go Sub Write document line
+++Undefine Field: FIELDS/+Subroutine
You should note that the last statement ensures that the normal handling performed by the subroutine is not generated.
The call to WpkaSetResponseCharset is is normally made in the subroutine itself, but as this handling has bee undefined, you have to enter the call in the post point.
The rest of the code just sets the values for the Content-Type and Content-disposition headers.
It seems the Chrome browser can't load the pdf inline if the target is a frame. This means that there can very well be problems when loading a pdf in a frame in WebsydianExpress. You can avoid this issue by specifying target=_top in the HTML form for the event that shows the pdf.
The media type for pdf is: application/pdf
When the default behavior is to show the file in the browser, the Content-disposition should be set to attachment - and a suggested filename should be specified.
Define the BinaryPageGenerator by specifying the triple:
Source Object | Verb | Target Object |
---|---|---|
MyBinaryPageGenerator | is a FNC | WSYBASE/BinaryPageGenerator |
Create two messages that will be used to create the Content-type and Content-disposition header values
Source Object | Verb | Target Object |
---|---|---|
MyBinaryPageGenerator | message MSG | ContentType |
MyBinaryPageGenerator | message MSG | ContentDisposition |
MyBinaryPageGenerator.ContentDisposition | parameter FLD | WSYBASE/DocumentName |
Specify the following literal values:
MyBinaryPageGenerator.ContentType: application/pdf
MyBinaryPageGenerator.ContentDisposition: attachment; filename="&(1:)"
In the Post Point "Start Send Headers enter the following code:
+If Variant: WsyBase/DWA - Windows
+Else
Call WsyBase/WpkaSetResponseCharset
Map with:
WsyBase<ConnectionPointer>
ResponseCharset<*BINARY>
Set Document<TypeInfo> = <TypeInfo.Specific>
Set Document<DocumentAction> = <DocumentAction.Open>
Set Local<HeaderName> = <HeaderName.Content-type>
Format Message Message: MyBinaryPageGenerator.ContentType, Local<HeaderValue>
Go Sub Write document line
Set Local<HeaderName> = <HeaderName.Content-disposition>
Format Message Message: MyBinaryPageGenerator.ContentDisposition, Local<HeaderValue>
Map with:
Document<DocumentName>
Go Sub Write document line
+++Undefine Field: FIELDS/+Subroutine
You should note that the last statement ensures that the normal handling performed by the subroutine will not be generated.
The call to WpkaSetResponseCharset is is normally made in the subroutine itself, but as this handling has been undefined, you have to enter the call in the post point.
The rest of the code just sets the values for the Content-Type and Content-disposition headers.
If you want to suggest a filename to the user that is not the same as the one used in your file system, specify a field containing this value for the parameter to the format message statement for the ContentDisposition message.
In Chrome 10, this will show a standard file/folder selection dialog. This only allows the user to save the file.
In Firefox 4, this shows a dialog, where the user can select to either save or open the file. The default will be the last selection the user has made.
In Internet Explorer 8, this shows a dialog where the user can select to either save or open the file. The default seems to be to cancel the download.
In Firefox 4, when you choose Content-disposition attachment, the user will be shown a dialog, where he can choose to either save the file or open it.
It seems that the selection will be the one the user has selected the last time - not necessarily the save option.
In some cases, the application should always propose that the file should be saved. This seems to be possible using a slightly different combination of Content-Type and Content-disposition.
In this case, you specify the Content-Type: application/force-download and the Content-disposition: attachment;filename="myfilename.pdf".
This instructs the application that it should always propose that the file should be saved.
Internet Explorer 8 and Chrome 10 seems to be indifferent to whether the Content-Type is set to application/pdf or to application/force-download.
Note that application/force-download is not a standard media type, so you can't be certain that all browsers will be able to handle it. Therefore, you should only use this if you need to ensure that the save option is selected when the user uses Firefox.
Define the BinaryPageGenerator by specifying the triple:
Source Object | Verb | Target Object |
---|---|---|
MyBinaryPageGenerator | is a FNC | WSYBASE/BinaryPageGenerator |
Create two messages that will be used to create the Content-type and Content-disposition header values
Source Object | Verb | Target Object |
---|---|---|
MyBinaryPageGenerator | message MSG | ContentType |
MyBinaryPageGenerator | message MSG | ContentDisposition |
MyBinaryPageGenerator.ContentDisposition | parameter FLD | WSYBASE/DocumentName |
Specify the following literal values:
MyBinaryPageGenerator.ContentType: application/force-download
MyBinaryPageGenerator.ContentDisposition: attachment; filename="&(1:)"
In the Post Point "Start Send Headers enter the following code:
+If Variant: WsyBase/DWA - Windows
+Else
Call WsyBase/WpkaSetResponseCharset
Map with:
WsyBase<ConnectionPointer>
ResponseCharset<*BINARY>
Set Document<TypeInfo> = <TypeInfo.Specific>
Set Document<DocumentAction> = <DocumentAction.Open>
Set Local<HeaderName> = <HeaderName.Content-type>
Format Message Message: MyBinaryPageGenerator.ContentType, Local<HeaderValue>
Go Sub Write document line
Set Local<HeaderName> = <HeaderName.Content-disposition>
Format Message Message: MyBinaryPageGenerator.ContentDisposition, Local<HeaderValue>
Map with:
Document<DocumentName>
Go Sub Write document line
+++Undefine Field: FIELDS/+Subroutine
You should note that the last statement ensures that the normal handling performed by the subroutine will not be generated.
The call to WpkaSetResponseCharset is is normally made in the subroutine itself, but as this handling has been undefined, you have to enter the call in the post point.
The rest of the code just sets the values for the Content-Type and Content-disposition headers.
If you want to suggest a filename to the user that is not the same as the one used in your file system, specify a field containing this value for the parameter to the format message statement for the ContentDisposition message.
In Chrome 10, this will show a standard file/folder selection dialog. This only allows the user to save the file.
In Firefox 4 and later, this shows a dialog, where the user can select to either save or open the file. The default will save.
In Internet Explorer 8, this shows a dialog where the user can select to either save or open the file.