Note that there are some explanatory texts on larger screens.

plurals
  1. POPHP PDF download script is executing twice
    primarykey
    data
    text
    <p>I have a web application using PHP and PDO with SQLSRV prepared statements to display links to files for users to download. The back-end PHP script 'download.php' checks various items before serving the PDF to the user to download. The download.php file then should update a few SQL tables, and serve the PDF file to the user.</p> <p>Please read my <a href="https://stackoverflow.com/questions/9280032/php-pdo-and-sqlsrv-executes-multiple-times-on-one-insert-statement">Previous Question</a> and the troubleshooting completed there, if you need more information. <br/></p> <p>After troubleshooting, the error I thought was occurring (and thus the previous question I had asked) was incorrect. My download script is getting executed more than once for every file download.</p> <p>I have searched the server logs and while debugging with Firebug, I can see my download.php script making multiple GET requests to the server. Sometimes the script completes only once as expected. Other times the script executes three to four request for the one click of the download link.</p> <p>Now that I more fully understand what error is occurring, I need a bit of help fixing it. I need to prevent the script from running multiple times, and thus updating the SQL table with records that are within a few milliseconds of each other.</p> <p>The view page checks the SQL database for files the current user is allowed access to, and displays a list of links:</p> <pre><code>&lt;a href='download.php?f={$item['name']}&amp;t={$type}' target='_blank'&gt;{$item['name']}&lt;/a&gt; </code></pre> <p>Because the values are needed for the download.php script to work, I cannot change the request to a $_POST instead of $_GET.</p> <p>What I have tried:</p> <ul> <li><p>Checking/setting a session variable for 'downloading' state, before the <code>getfile()</code> which unsets right before the <code>exit(0)</code></p></li> <li><p>Putting the SQL statements in a separate PHP file and require'ing that </p></li> <li><p>Adding a <code>sleep(1)</code> after the <code>getfile()</code></p></li> <li><p>Commenting out the header/PDF information</p></li> </ul> <p>The first three measures did not work to prevent the double/triple execution of the PHP download script. However, the last measure DOES prevent the double/triple execution of the PHP script, but of course the PDF is never delivered to the client browser!</p> <p><strong>Question</strong>: How can I ensure that only ONE insert/update PER DOWNLOAD is inserted into the database, or at the least, how can I prevent the PHP script from being executed multiple times?</p> <p><strong>UPDATE</strong></p> <p>Screenshot of issue in firebug:</p> <p>One request: <img src="https://i.imgur.com/erpns.png" alt="one"></p> <p>Two requests: <img src="https://i.imgur.com/uWNpi.png" alt="two"></p> <p><strong>download.php script</strong></p> <pre><code>&lt;?php session_start(); require("cgi-bin/auth.php"); // Don't timeout when downloading large files @ignore_user_abort(1); @set_time_limit(0); //error_reporting(E_ALL); //ini_set('display_errors',1); function getfile() { if (!isset($_GET['f']) || !isset($_GET['t'])) { echo "Nothing to do!"; exit(0); } require('cgi-bin/connect_db_pdf.php'); //Update variables $vuname = strtolower(trim($_SESSION['uname'])); $file = trim(basename($_GET['f'])); //Filename we're looking for $type = trim($_GET['t']);//Filetype if (!preg_match('/^[a-zA-Z0-9_\-\.]{1,60}$/', $file) || !preg_match('/^av|ds|cr|dp$/', $type)) { header('Location: error.php'); exit(0); } try { $sQuery = "SELECT TOP 1 * FROM pdf_info WHERE PDF_name=:sfile AND type=:stype"; $statm = $conn-&gt;prepare($sQuery); $statm-&gt;execute(array(':sfile'=&gt;$file,':stype'=&gt;$type)); $result = $statm-&gt;fetchAll(); $count = count($result); $sQuery = null; $statm = null; if ($count == 1 ){ //File was found in the database so let them download it. Update the time as well $result = $result[0]; $sQuery = "INSERT INTO access (PDF_name,PDF_type,PDF_time,PDF_access) VALUES (:ac_file, :ac_type, GetDate(), :ac_vuname); UPDATE pdf_info SET last_view=GetDate(),viewed_uname=:vuname WHERE PDF_name=:file AND PDF_type=:type"; $statm = $conn-&gt;prepare($sQuery); $statm-&gt;execute(array( ':ac_vuname'=&gt;$vuname, ':ac_file'=&gt;$file, ':ac_type'=&gt;$type,':vuname'=&gt;$vuname, ':file'=&gt;$file, ':type'=&gt;$type)); $count = $statm-&gt;rowCount(); $sQuery = null; $statm = null; //$result is the first element from the SELECT query outside the 'if' scope. $file_loc = $result['floc']; $file_name = $result['PDF_name']; // Commenting from this line to right after the exit(0) updates the database only ONCE, but then the PDF file is never sent to the browser! header("Content-Type: application/pdf"); header("Pragma: no-cache"); header("Cache-Control: no-cache"); header("Content-Length: " . filesize($file_loc)); header("Accept-Ranges: bytes"); header("Content-Disposition: inline; filename={$file_name}"); ob_clean(); flush(); readfile($file_loc); exit(0); } else { //We did not find a file in the database. Redirect the user to the view page. header("Location: view.php"); exit(0); } } catch(PDOException $err) {//PDO SQL error. //echo $err; header('Location: error.php'); exit(0); } } getfile(); ?&gt; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload