blob: db624f6d97c5e60067d3b3f5e872c7e207923c56 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>File Download with Rivet</title>
<link rel="stylesheet" href="../templates/wondrous/styles.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="header">
<h1><a href="../index.html">Rivet</a></h1>
<h2 id="slogan">Webscripting for Tcl'ers</h2>
<div class="clear"></div>
</div>
<div id="body">
<div id="content">
<h2>File Download with Rivet</h2>
<div class="example">
<!-- p class="title"><b>Example 5. File Download</b></p-->
<div class="example-contents">
<p>
In general setting up a data file for being sent over http is as easy as determining the file's
URI and letting Apache's do all that is needed. If this approach fits your design all you have to do
is to keep the downloadable files somewhere within Apache's DocumentRoot (or in any of the directories
Apache has right to access).
</p>
<p>
When a client sends a request for a file, Apache takes care of determining the filetype, sends appropriate
headers to the client and then the file content. The client is responsible for deciding how to handle the
data accordingly to the <quote>content-type</quote>
headers and its internal design.
For example when browsers give up
trying to display a certain "content-type" they display a download dialog box asking for directions from the user.
</p>
<p>
Rivet can help if you have more sofisticated needs. For instance you may be developing an application that uses
webpages to collect input data. This information might be passed on to scripts or programs for processing.
In this case a real file representing the data doesn't exist and the content is generated on demand by the server.
In other circumstances you may need to dynamically inhibit the download of specific files and hide them away,
your scripts may expunge from the pages every link to these files (your pages are dynamic, aren't they?)
and move them out of way, but it looks like a cumbersome solution.
</p>
<p>
Putting Tcl and Rivet in charge of the whole download mechanism helps in building
cleaner and safer approaches
to the download problem.
</p>
<p>
In this example a procedure checks for the existence of a parameter passed in by the browser. The parameter is
the name (without extension) of a pdf file. Pdf files are stored in a directory whose path is in the
<b>pdf_repository</b>
variable.
</p>
<p>
This code is reported as an example of how to control the protocol using the headers command.
</p>
<pre class="programlisting"># Code example for the transmission of a pdf file.
if {[var exists pdfname]} {
set pdfname [var get pdfname]
# let's build the full path to the pdf file. The 'pdf_repository'
# directory must be readable by the apache children
set pdf_full_path [file join $pdf_repository ${pdfname}.pdf]
if {[file exists $pdf_full_path]} {
# Before the file is sent we inform the client about the file type and
# file name. The client can be proposed a filename different from the
# original one. In this case, this is the point where a new file name
# must be generated.
headers type "application/pdf"
headers add Content-Disposition "attachment; filename=${pdfname}.pdf"
headers add Content-Description "PDF Document"
# The pdf is read and stored in a Tcl variable. The file handle is
# configured for a binary read: we are just shipping raw data to a
# client. The following 4 lines of code can be replaced by any code
# that is able to retrieve the data to be sent from any data source
# (e.g. database, external program, other Tcl code)
set paper [open $pdf_full_path r]
fconfigure $paper -translation binary
set pdf [read $paper]
close $paper
# Now we got the data: let's tell the client how many bytes we are
# about to send (useful for the download progress bar of a dialog box)
headers add Content-Length [string length $pdf]
# Let's send the actual file content
puts $pdf
} else {
parse pdf_not_found_error.rvt
}
} else {
parse parameter_not_defined_error.rvt
}</pre>
<p>
Before the pdf is sent the procedure sets the Content-Type, Content-Disposition, Content-Description and
Content-Length headers to inform the client about the file type, name and size. Notice that in order to
set the Content-Type header Rivet uses a specialiezed form of the headers command. Headers must be sent before
data gets sent down the output channel. Messing with this prescription causes an error to be raised (in fact
the protocol itself is being violated)
</p>
</div>
</div>
<div class="contentbottom">
</div>
</div>
<div class="sidebar">
<ul>
</ul>
<ul>
<li id="home">
<h4>Rivet</h4>
<ul class="blocklist">
<li class="navitem">
<a title="A home for Rivet" href="../index.html">Rivet Homepage</a>
</li>
<li class="navitem">
<a title="Home of Apache Tcl related stuff" target="asf" href="http://tcl.apache.org/">Apache Tcl Home</a>
</li>
<li class="navitem">
<a title="Getting Rivet" href="download.html">Getting Rivet</a>
</li>
<li class="navitem">
<a title="Hello World!" href="hello%5fworld.html">Examples</a>
</li>
<li class="navitem">
<a title="The Rivet development team" href="about.html">About Us - Contact</a>
</li>
</ul>
</li>
<li id="manual">
<h4>Documentation</h4>
<ul class="blocklist">
<li class="navitem">
<a title="Rivet 2.1 Manual" target="rivetman2.1" href="http://tcl.apache.org/rivet/manual2.1/">Rivet 2.1</a>
</li>
<li class="navitem">
<a title="Rivet 2.2 Manual" target="rivetman2.2" href="http://tcl.apache.org/rivet/manual2.2/">Rivet 2.2</a>
</li>
<li class="navitem">
<a title="Rivet 2.3 Manual" target="rivetman2.3" href="http://tcl.apache.org/rivet/manual2.3/">Rivet 2.3</a>
</li>
<li class="navitem">
<a title="Rivet 3.0 Manual" target="rivetman3.0" href="http://tcl.apache.org/rivet/manual3.0/">Rivet 3.0</a>
</li>
</ul>
</li>
<li id="rivetexamples">
<h4>Examples</h4>
<ul class="blocklist">
<li class="navitem">
<a href="hello%5fworld.html">Hello world!</a>
</li>
<li class="navitem">
<a href="colorful%5ftable.html">A colorful table</a>
</li>
<li class="navitem">
<a href="var%5faccess.html">Variable Access</a>
</li>
<li class="navitem">
<a href="file%5fupload.html">File Upload</a>
</li>
<li class="navitem">
<a href="file%5fdownload.html">File Download</a>
</li>
<li class="navitem">
<a href="ajax.html">XML and Ajax</a>
</li>
<li class="navitem">
<a href="calendar.html">Calendar</a>
</li>
</ul>
</li>
</ul>
<ul>
</ul>
</div>
<div class="clear"></div>
</div>
</div>
<div id="footer">
<div class="footer-content">
<p><a href="http://www.apache.org/">Apache Software Foundation</a> | Design by <a href="http://www.spyka.net">Free CSS Templates</a> | <a href="http://www.justfreetemplates.com">Free Web Templates</a></p>
</div>
</div>
<div style="text-align: center; font-size: 0.75em;">Design downloaded from <a href="http://www.freewebtemplates.com/">free website templates</a>.</div></body>
</html>