--- In advanced_delphi@yahoogroups.com, "Doug Hale" <del...@...> wrote: > > I am having problems sending .pdf files from a CGI application. > > My code: > > Filename := Path+Document+'.pdf'; > Fs := TFileStream.Create(Filename, fmOpenRead, fmShareDenyNone); > Response.ContentType := 'application/pdf'; > Response.ContentStream := Fs; > > > The problem is that sometimes the file is not sent. The HTTP request needs to be sent more than once to get the document actually sent. > > Do I need to do > > Response.SendResponse; > > after the above code? > > Am I doing something I shouldn't or not doing something I should.
I don't know how to do this in Delphi, but here is some PHP code that does what you want. This code is used to serve up members-only and public files, depending on the user's authentication. The files are stored in directories that are inaccessible to the web server and are streamed out to the browser upon request. This function also keeps track of download counts and the last time a file was downloaded in a MySQL database. This function took a LOT of tweaking to get it to work reliably on multiple browsers and file types. It now works great on all the listed file types and has been in continuous use for several years. The HTTP headers gave me the most headaches during development - look closely at that part. I do use Delphi to manage the database end of this code. :-) // This function looks up a file in the filelist table and serves it to the end-users browser // We send the file type along with the file binary stuff, so the user's browser *should* open the // file with the correct application. function fetch_file($id_field, $id_value) { $ret = FILEOK; $link = connect(); $q = "SELECT filename, membersonly from filelist WHERE " . $id_field . " = '" . $id_value . "';"; $res = mysql_query($q); if ($res) { if (mysql_num_rows($res) > 0) { // just get the first match $row = mysql_fetch_row($res); $filename = $row[0]; if (($row[1] == "N") or (SecCheck())) // check user authorization if not a public file { disconnectcw($link); if (!is_file($filename) || connection_status() != 0) { // can't find the file return FILEERROR; } // to prevent long file from getting cut off from //max_execution_time set_time_limit(0); // filenames in IE containing dots will screw up the // filename unless we add this //if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) // $filename = preg_replace('/\./', '%2e', $filename, substr_count($file, '.') - 1); // $file_extension = strtolower(substr(strrchr($filename, "."), 1)); switch ($file_extension) { case "pdf": $ctype = "application/pdf"; break; case 'txt': $ctype = "text/plain"; break; case "exe": $ctype = "application/octet-stream"; break; case "zip": $ctype = "application/zip"; break; case "doc": $ctype = "application/msword"; break; case "xls": $ctype = "application/vnd.ms-excel"; break; case "ppt": $ctype = "application/vnd.ms-powerpoint"; break; case "gif": $ctype = "image/gif"; break; case "png": $ctype = "image/png"; break; case "mp3": $ctype = "audio/mp3"; break; case "jpe": case "jpeg": case "jpg": $ctype = "image/jpg"; break; default: $ctype = "application/force-download"; } header("Pragma: public"); // required if (ini_get('zlib.output_compression')) ini_set('zlib.output_compression', 'Off'); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past to make cache expire header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private", false); header("Content-Type: $ctype"); header("Content-Disposition: attachment; filename=" . basename($filename) . ";"); header("Content-Transfer-Encoding: binary"); header("Content-Length: " . filesize($filename)); if($file = fopen($filename, 'rb')) { $link = connect(); $q = "update filelist set downloadcount=(downloadcount+1), lastdownload=NOW() WHERE " . $id_field . " = '" . $id_value . "';"; $res = mysql_query($q); disconnectcw($link); // Stream the file out to the guy's browser, 8K at a time... while( (!feof($file)) && (connection_status()==0) ) { print(fread($file, 8192)); flush(); } fclose($file); } if ((connection_status() == 0) and !connection_aborted()) { return FILEOK; } else return FILEERROR; } else return SECERROR; } else { return FILEERROR; } } else { return DBERROR; } }