Forum OpenACS Q&A: Help for using HTMLDOC to output pdf file/download pdf file

Hi. All.

I have openacs3.x running on my dev box and am trying to figure out
how to use HTMLDOC to output pdf file.

I create a filter similar to file-storage and a proc similiar to fs-
file-downloader, which creates a link for user to download a pdf file
created by htmldoc in the /tmp directory.

The code of the proc is "

proc_doc pdf_downloader {conn key } "" {


    if { [empty_string_p $file_name] } {

    return filter_break


    set file_name_html "$file_name.html"

    set file_name_pdf "$file_name.pdf"

    if {[catch {exec htmldoc --webpage -f $file_name_pdf
$file_name_html} errmsg]} {

    ad_return_error Error $errmsg


    ns_returnfile 200 "application/pdf" $file_name_pdf

    return filter_return

This proc is invoked by this link "/document/doc.pdf?
file_name=/tmp/docXXXXXX", which is created by another proc.
$file_name_html is already created in /tmp directory.

I put "
ns_section "ns/mimetypes"
ns_param  ".pdf"          "application/pdf"
" in nsd.tcl file.

It works well till the last step, which gives me the following error:
PAGES: 1 BYTES: 3612

If I reload the page, it gives me some additional info:

PAGES: 1 BYTES: 3612

HTTP/1.0 200 OK MIME-Version: 1.0 Date: Fri, 03 May 2002 01:25:01 GMT
Server: AOLserver/3.4.2 Content-Type:
text/html Content-Length: 245 Connection: close Last-Modified: Fri,
03 May 2002 01:25:01 GMT Content-Type:
application/pdf Content-Length: 3612 %PDF-1.3 %âãÏ

Don't know exactly what the problem is. The pdf file is created in
the /tmp directory but is not returned to the browser.

I tried file-storage module to upload a pdf file and I can download
it from the link created by fs-file-downloader. But that page uses
db_blob to return the file.

Is this a problem with mime type? Ns_returnfile doesn't return that
pdf file correctly.

I tried "ns_write "output-type : application/pdf" $file_name_pdf"
and "ns_respond -status 200 -type "application/pdf" -file
$file_name_pdf" and both don't work.

Any feedback is appreciated!

From the output you posted it looks like ns_returnfile correctly does return the pdf as desired, but something else outputs the string "Error PAGES: 1 BYTES: 3612 mailto:webmaster@localhost.localdomain"; to the connection before that, which screws up the headers, which obviously confuses the browser.

It propably has to do something with the exec call. I'd first try to comment the exec out, put a pregenerated pdf in /tmp/ and see if you can return that with ns_returnfile. If that works then try to redirect stderr and stdout of the exec to /dev/null ("man 3tcl exec" tells you how).

Have you tried

exec htmldoc --webpage --quiet -f $file_name_pdf $file_name_html ?

Try adding --quiet to your htmldoc call.  That appears to be the standard output from htmldoc you're seeing.
Thanks. All.

"--quiet" fixes the problem.  Wow! I guess I didn't dig enough in HTMLDOC documentation.

Thanks again!

Hi. All.

I have used htmldoc to create pdf file in OACS3.X and I can download it from browser.

Now I installed OACS4.5 beta and have everything worked. When I try to create the same function for creating and downloading pdf file, I can't make it work.

If I upload a pdf file in File Storage Root Folder, in OACS3.x, it doesn't require a download folder, but in OACS4.5, a download folder exists. And there is a index.vuh file, which handles virtual url handler. And in the file storage package of 4.5, I can't download a pdf file after I upload it. There is a blank screen for the page

I don't know what's the new rule for creating virtual url handler.

The code I use for creating and downloading pdf file is the same as the pdf_downloader proc above-mentioned. And I see the html file and pdf file in the tmp after I click on the virtual url. But it can't be downloaded from that virtual url. Is it a permission problem or configuration problem?

BTW, I put
ns_param  ".pdf"          "application/pdf"
in ns_section "ns/mimetypes".

Any idea?

Thanks in advance,

Are you using exactly the same procedure as in the original question? Then the problem might be with using set_the_usual_form_variables - I am not sure if that still works as expected under OpenACS 4.x. Try to pass the file_name directly to the proc instead, something like:

ad_proc pdf_downloader { file_name } { } {

if { [empty_string_p $file_name] } ... and so on
Thanks.  Tilmann .

I copied the set_the_usual_form_variable to the OACS4.5 and make it works. The file name can be passed into the pdf_downloader procedure. And the html file and pdf file can be generated. The only problem is that server doesn't serve pdf file out.

ns_returnfile 200 "application/pdf" $file_name_pdf. This code doesn't return anything.

I guess the problem is the permission issue of serving virutal url in new OAC4.5. Can someone who developed the new file-storage package give some hints?



Running exec on htmldoc would successfully execute the shell commands, but return this error:

  child process exited abnormally

This would ruin my ns_returnfile since output was sent to the browser before the 200 header.

I discovered htmldoc returns 1 on success to stdout which is returned by catch and exec. Just catch the error and do nothing with it.

# Download the pdf
set file_name_pdf [ns_tmpnam]
append file_name_pdf ".pdf"

if {[catch {exec echo \ $html\  | /usr/share/htmldoc/htmldoc --webpage --quiet -f $file_name_pdf -} errmsg]} {
#Do nothing with the error and we're good.

ns_returnfile 200 application/pdf $file_name_pdf

return filter_return

Oh, and concerning the strangeness with
  echo \[space]$html\[space]
This is the only way to simulate shell quotes with exec. Curly braces and \" do not seem to work. Remember that $html must be escaped - "[{ etc!

More info on exec:

Hope this helps someone.