PHP, X-SendFile: отправка файла вместе с выводом текста в браузер (через echo)

0

Я использую X-SendFile Apache Module для загрузки больших файлов с сервера. Загрузки работают хорошо. Однако, когда начинается загрузка, мне нужно вывести в браузер какой-то текст, например: "Спасибо за загрузку файла..."

Моя проблема заключается в том, что я не могу выполнять оба сценария. Я могу либо загрузить файл, а затем текст не выводится на экран. Или, я могу вывести текст на экран, но тогда сценарий загрузки не запустится.

Как выполнить обе задачи в одном php-скрипте, пожалуйста, загрузите файл и отправьте текстовый контент в браузер/веб-страницу? Проблема, вероятно, возникает в заголовках выходных данных HTTP, но я не знаю, как ее решить.

Это пример кода, который я использую для загрузки файлов через X-SendFile (работает правильно самостоятельно):

                header('Content-Description: File Transfer');
                header("Content-Disposition: attachment; filename=\"". basename($filePath) . "\"");
                header('Content-Transfer-Encoding: binary');
                header('Expires: 0');
                header('Cache-Control: no-store, no-cache, must-revalidate');
                header('Pragma: no-cache');
                header('Content-Length: ' . filesize($filePath));
                header("X-Sendfile: $filePath");

Для завершения это моя тестовая echo"" строка. Если он помещен над кодом X-Sendfile, он выводится, но загрузка не запускается. Если он помещен ниже кода X-Sendfile, файл загружается, а nothign - в браузере:

echo "SUCCESS!!!";
ob_flush();

Ограничение:

Мне нужно иметь возможность загружать файл eaisly через URL. Пример: www.mydomain.com/?fileID=asl523n53twteHLfga. Другими словами, скрипт загрузки PHP находится внутри index.php. Когда пользователь входит на сайт www.mydomain.com, отображается целевая страница домена. Однако, когда передается дополнительная переменная $_GET, скрипт PHP распознает это и должен отображать Спасибо за загрузку... вместо целевой страницы.

Обходной путь приветствуется. Важно следить за желаемым результатом, сохраняя вышеуказанное ограничение. Тыкн ты очень.

  • 2
    Невозможно. HTTP-составная часть вообще не поддерживается (или не поддерживается) большинством браузеров. ответ обычно состоит из ОДНОГО потока данных. большинство людей обходит, выскакивая промежуточную страницу с благодарностью, а затем мета-обновление, которое указывает на фактическую ссылку для скачивания.
  • 0
    Марк Б, спасибо за ваш ответ. Я понимаю, что вы имеете в виду. Это действительно выполнимое решение. Я буду ждать, чтобы собрать еще несколько ответов, и если ничего не получится, я пойду в указанном вами направлении. Спасибо и +1.
Теги:
x-sendfile

2 ответа

2
Лучший ответ

Как насчет добавления отдельной страницы загрузки, которая будет загружать файл (например, download.php?fileID=XYZ), и на вашей индексной странице появится такое сообщение:

<?php

function homeScreen() {
  // your home content
}

function downloadFileScreen ($id) {
?>
<h2>Thank you for your download!</h2>
Your download should start automatically, if it does not, click 
<a href="download.php?fileID=<?php print $id; ?>">here</a>
<script type="text/javascript">
window.setTimeout('location.href="download.php?fileID=<?php print $id; ?>"',3000);
</script>
<?php
}

if (isset($_GET['fileID'])) {
  $id= $_GET['fileID'];
  downloadFileScreen ($id);
?>
} else {
  // no ID passed, show home screen
  homeScreen();
}
?>

Я не слышал о какой-либо поддержке браузера, смешивающей как загрузку, так и отображение содержимого HTTP в одном запросе, но я посмотрю, может ли это быть достигнуто с помощью ob_start() и ob_flush().

  • 1
    Привет Саша, я реализовал твоё решение (таким образом, что оно работает только для меня), и оно работает хорошо. Позвольте мне поблагодарить вас за ваш ответ и отметить его как принятый ответ. Благодарю.
  • 0
    Большое спасибо, рад, что это может помочь вам начать!
2

Существует обходное решение. Вы можете создать iframe, внутри которого загрузите файл. Подробнее см. В коде.

Спасибо за страницу: (например, www.mydomain.com/?fileID=asl523n53twteHLfga)

<p>Thank you!</p>
<?php
$fileID = $_REQUEST['fileID'];
// csrf code individual for visitor, so visitor can send direct link to friend
$csrf = md5(uniqid(rand(), true));
$_SESSION['csrf'] = $csrf;
// with iframe file will be downloaded 'in background'
echo '<iframe src="downloadFile.php?fileID=' . urlencode($fileID) . '&csrf=' . urlencode($csrf) . '" width="0" height="0"></iframe>';
?>

downloadFile.php (например, www.mydomain.com/downloadFile.php?fileID=asl523n53twteHLfga)

<?php
$fileID = $_REQUEST['fileID'];
if ($_REQUEST['csrf'] == $_SESSION['csrf'])
{
    // download file
    header('Content-Description: File Transfer');
    header("Content-Disposition: attachment; filename=\"". basename($filePath) . "\"");
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: no-store, no-cache, must-revalidate');
    header('Pragma: no-cache');
    header('Content-Length: ' . filesize($filePath));
    header("X-Sendfile: $filePath");
    die();
}
else
{
    // csrf from request not equal csrf saved in session, so probably this is direct link to file received from other user
    // redirect to 'thank you' page
    header('Location: /?fileID=' . urlencode($fileID));
    die();
}
?>
  • 1
    Привет и спасибо за ваш ответ. Ваш ответ содержит отличный пример, я думаю, он будет работать безупречно. Приведенное выше решение от Саши является еще одним прекрасным примером. Я попробовал решение Саши, и оно сработало для меня. Поскольку я должен принять решение, которое я отмечу как принятый ответ, я приму решение за Сашу, поскольку его ответ я действительно выполнил. Я дам вам +1 за ваш отличный совет. Спасибо.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню