Я уже некоторое время использую PDO и PHP с серверами MySQL и Apache. Недавно мне было поручено преобразовать устаревшее веб-приложение для бизнеса в новую настройку. Старая установка - это стандартный веб-стек Linux (Apache / PHP / MySQL / Filezilla), а новой установкой будет Windows Server 2003 с IIS / PHP (быстрая установка cgi) / SQL Server 2003 / без FTP.
У меня почти все работает, кроме преобразования оператора MySQL для обновления таблицы с информацией о доступе к файлам. Используя PDO с драйвером SQLSRV и выполнив оператор вставки внутри PHP-скрипта 'file download', вставляет несколько записей в таблицу SQL.
download.php выдает несколько запросов к серверу SQL. Один раз, чтобы проверить существование файла и переменных в одной таблице, а затем обновляет другую таблицу с информацией о доступе.
СМОТРИТЕ НИЖЕ ДЛЯ КОДА download.php
Отладка показывает печать / эхо $ count как 1. Однако при проверке записей сервера SQL всегда отображается БОЛЕЕ, чем одна вставленная. Иногда это всего лишь одна дополнительная строка из двух, но в других случаях она достигает четырех вставляемых операторов EXTRA. $ count остается показанным как 1, в каждом случае.
Этот конкретный скрипт PHP проверяет информацию в базе данных SQL перед вызовом этого оператора вставки. Сначала проверка подлинности для доступа к файлу (успешно), проверка существования файла (успешно), затем обновляет таблицу доступа с информацией для загрузки (ОШИБКА) и, наконец, предоставляет PDF для пользователя (успешно).
Когда я выполняю инструкцию INSERT вручную в Query Analyzer, он выполняется успешно и работает как положено; он вставляет один ряд каждый раз. Похоже, ошибка связана с реализацией execute () в SQLSRV или PDO.
Я искал информацию об этом в stackoverflow, serverfault и всемогущем Google. Возвращаются единственные типы результатов, когда пользователям нужно выполнить несколько запросов / вставок в одном операторе / execute. Где моя проблема противоположна; Однако я хочу выполнить только ОДНУ оператор вставки, более одного всегда выполняется.
Вопрос: почему это происходит и как я могу предотвратить множественную вставку?
ОБНОВЛЕНИЕ ПО ЗАПРОСУ
Код, который обращается к этому файлу, представляет собой одну единственную ссылку с другой веб-страницы. На странице перечислены текущие файлы, к которым пользователь имеет доступ, и представлены ссылки на скрипт download.php для проверки, обновления и фактического предоставления PDF.
Страница просмотра имеет список ссылок (напечатанных в цикле for), расположенных следующим образом:
<a href='download.php?f={$item['name']}&t={$type}' target='_blank'>{$item['name']}</a>
Когда пользователь нажимает на эту ссылку, сценарий, приведенный ниже, запускается в дополнение к другому приведенному выше коду для download.php. Он успешно обслуживает файл PDF. Содержимое отправляется download.php в виде заголовка PHP / встроенного PDF:
СМОТРЕТЬ НИЖЕ ДЛЯ КОДА
Просмотр журналов сервера показывает два GET-запроса к файлу download.php:
2012-02-14 17:44:37 W3SVC1785071458 172.17.31.254 GET /download.php f=06304844-1A.pdf&t=av 4090 - 172.17.31.112 Mozilla/5.0+(Windows+NT+6.1)+AppleWebKit/535.7+(KHTML,+like+Gecko)+Chrome/16.0.912.77+Safari/535.7 200 0 0
2012-02-14 17:44:37 W3SVC1785071458 172.17.31.254 GET /download.php f=06304844-1A.pdf&t=av 4090 - 172.17.31.112 Mozilla/5.0+(Windows+NT+6.1)+AppleWebKit/535.7+(KHTML,+like+Gecko)+Chrome/16.0.912.77+Safari/535.7 200 0 0
Я тестировал в Firefox, Opera и IE (6-9b), и результаты совпадают.
ОБНОВЛЕНИЕ ВТОРОЕ
Размещение всего файла download.php здесь:
<?php
session_start();
require("cgi-bin/auth.php");
// Don't timeout when downloading large files
@ignore_user_abort();
@set_time_limit(0);
//error_reporting(E_ALL);
//ini_set('display_errors',1);
function getfile() {
require('cgi-bin/connect_db_pdf.php');
//Verify information
if (!isset($_GET) || !isset($_GET['f']) || !isset($_GET['t'])) {
echo "Nothing to do!";
exit(0);
}
//Update variables
$vuname = strtolower(trim($_SESSION['uname']));
$file = trim($_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)) {
echo "Non conforming values";
exit(0);
}
try {
$sQuery = "SELECT * FROM pdf_info WHERE PDF_name=:file AND PDF_type=:type";
$statm = $conn->prepare($sQuery);
$statm->execute(array(':file'=>$file,':type'=>$type));
$result = $statm->fetch();
$count = $statm->rowCount();
$sQuery = null;
$statm = null;
if ($count == 1 ){ //File was found in the database so let them download it. Update the time as well
$sQuery = "INSERT INTO access (PDF_name,PDF_type, PDF_time, PDF_access) VALUES (:file, :type, GetDate(), :vuname)";
$statm = $conn->prepare($sQuery);
$statm->execute(array( ':vuname'=>$vuname, ':file'=>$file, ':type'=>$type));
$count = $statm->rowCount();
$sQuery = null;
$statm = null;
$sQuery = "UPDATE pdf_info SET last_view=GetDate(),viewed_uname=:vuname WHERE PDF_name=:file AND PDF_type=:type";
$statm = $conn->prepare($sQuery);
$statm->execute(array( ':vuname'=>$vuname, ':file'=>$file, ':type'=>$type));
$sQuery = null;
$statm = null;
//$result is from FIRST SELECT query outside this 'if' scope.
$file_loc = $result['floc'];
$file_name = $result['filename'];
$fileh = fopen($file_loc,'rb');//Send content to browser as inline PDF
header("Content-Type: application/pdf");
header("Pragma: no-cache");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Length: " . filesize($file_loc));
header("Accept-Ranges: bytes");
header("Content-Disposition: inline; filename={$file_name}");
while (!feof($fileh)) {
echo(@fgets($fileh, 8192));
}
fclose ($fileh);
exit(0);
} else { //We did not find a file in the database. Redirect the user to the view page.
header("Location: view.php");
}
} catch(PDOException $err) {//PDO SQL error.
//echo $err;
header('Location: error.php');
exit(0);
}
}
getfile();
?>