Создание ссылки для скачивания файла .jpg с использованием PHP - PullRequest
2 голосов
/ 13 октября 2009

Думаю, это должно быть легко. У меня есть галерея изображений с разбивкой по страницам, и под каждым изображением есть небольшая ссылка с надписью «Скачать комп». Это должно позволить людям быстро загрузить файл .jpg (с сгенерированным PHP водяным знаком) на свой компьютер.

Теперь я знаю, что могу просто ссылаться прямо на файл .jpg, но для этого необходимо, чтобы пользователь открыл изображение в новом окне, щелкнул правой кнопкой мыши, Сохранить как ... и т. Д. Вместо этого я хочу " Download Comp ", чтобы начать загрузку файла немедленно.

PHP.net, похоже, предлагал использовать readfile (), поэтому каждая ссылка «Скачать комп» отображается как «? Download = true & g = {$ gallery} & i = {$ image}».

Затем в верхней части страницы я вижу, что переменная $ _GET ['download'] установлена, и если да, я запускаю следующий код:

if(isset($_GET['download'])) {
$gallery = $_GET['g'];
$image = $_GET['i'];
$file = "../watermark.php?src={$gallery}/images/{$image}";
header('Content-Description: File Transfer');
    header('Content-Type: application/jpeg');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: public');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
readfile($file);

}

Ссылка занимает много времени, а затем выдает диалоговое окно с просьбой открыть или сохранить файл, но после сохранения и попытки открыть его, он говорит, что файл поврежден и не может быть открыт.

Есть идеи?

Ответы [ 5 ]

4 голосов
/ 14 октября 2009

Не устанавливайте $ file для относительного URL. Функция readfile попытается получить доступ к файлу php на сервере. Это не то, что вы хотите. В вашем случае это выглядит так, как будто файл watermark.php отправит нужное вам содержимое, так что вы можете просто настроить необходимую среду и включить ее.

<?php
if(isset($_GET['download'])) {
    $gallery = $_GET['g'];
    $image = $_GET['i'];
    $_GET['src'] = "{$gallery}/images/{$image}";

    header('Content-Description: File Transfer');
    header('Content-Type: image/jpeg');
    header('Content-Disposition: attachment; filename='.basename($image));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: public');
    header('Pragma: public');
    ob_clean();
    include('../watermark.php');
    exit;
}

Другой (более простой) способ - изменить watermark.php. Добавьте параметр запроса, чтобы он отправлял правильные заголовки для принудительной загрузки и ссылку на этот

<a href="watermark.php?src=filename.jpg&download=true)">...</a>

watermark.php:

<?php
if (isset($_GET['download']) && $_GET['download'] == 'true') {
    header('Content-Description: File Transfer');
    header('Content-Type: image/jpeg');
    header('Content-Disposition: attachment; filename='.basename($src));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: public');
    header('Pragma: public');
}
// continue with the rest of the file as-is

Кроме того, вам не нужен вызов для сброса (). Там не должно быть никакого вывода для отправки в этой точке, так что это не обязательно.

1 голос
/ 13 октября 2009

Это похоже на проблему безопасности.

Что если кто-то введет:

$g = '../../../../../../';
$i = '../../sensitive file at root';

Как насчет создания .htaccess (если вы используете apache) i для каталога галереи служит jpegs для загрузки вместо обычной.

1 голос
/ 13 октября 2009
header('Content-Type: image/jpeg');

Возможно

0 голосов
/ 13 октября 2009

Также попробуйте file_get_contents() вместо readfile(). Я считаю, что это работает при большем количестве обстоятельств. Я также рекомендовал бы использовать ob_flush() после вывода данных изображения. Мне никогда не приходилось использовать ob_clean() или flush(), чтобы заставить работать подобные вещи.

И, как сказал Эрик, вы также, возможно, захотите позвонить по номеру exit(), чтобы он был для хорошей меры, если он все еще не работает, на случай, если в конце вы застряли некоторые ненужные данные. *

0 голосов
/ 13 октября 2009

Я думаю, что вам может потребоваться выполнить вызов readfile() с вызовом exit(), чтобы убедиться, что больше ничего не записывается в выходной буфер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...