За последние 24 часа нас посетили 20789 программистов и 1137 роботов. Сейчас ищут 359 программистов ...

Открыть файл в новой вкладке, получив его сервера.

Тема в разделе "PHP для новичков", создана пользователем Nemoj, 19 авг 2020.

  1. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    На сервере есть папки с файлами.
    Настроил загрузку фалов, настроил скачивание файлов, и даже переименование.
    Как теперь сделать чтобы файл открылся для просмотра в новой вкладке браузера?
    На сервере маршрутизация моя. Прямой ссылки на файл нет, передаю имя файла параметром post запроса. Скачиваю вот так https://daruse.ru/loadfile-php

    Код (Text):
    1. <?php
    2. $filename = $_GET['filename'];
    3.  
    4. // иначе Internet Explorer будет игнорировать Content-Disposition
    5. if(ini_get('zlib.output_compression'))
    6.   ini_set('zlib.output_compression', 'Off');
    7.  
    8. $file_extension = strtolower(substr(strrchr($filename,"."),1));
    9.  
    10. if( $filename == "" )
    11. {
    12.           echo "ОШИБКА: УКАЖИТЕ ИМЯ ФАЙЛА.";
    13.           exit;
    14. } elseif ( ! file_exists( $filename ) ) // проверяем файл на существование
    15. {
    16.           echo "ОШИБКА: данного файла не существует.";
    17.           exit;
    18. };
    19. switch( $file_extension )
    20. {
    21.           case "pdf": $ctype="application/pdf"; break;
    22.           case "exe": $ctype="application/octet-stream"; break;
    23.           case "zip": $ctype="application/zip"; break;
    24.           case "doc": $ctype="application/msword"; break;
    25.           case "xls": $ctype="application/vnd.ms-excel"; break;
    26.           case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
    27.           case "mp3": $ctype="audio/mp3"; break;
    28.           case "gif": $ctype="image/gif"; break;
    29.           case "png": $ctype="image/png"; break;
    30.           case "jpeg":
    31.           case "jpg": $ctype="image/jpg"; break;
    32.           default: $ctype="application/force-download";
    33. }
    34. header("Pragma: public");
    35. header("Expires: 0");
    36. header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    37. header("Cache-Control: private",false); // нужен для Explorer
    38. header("Content-Type: $ctype");
    39. header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
    40. header("Content-Transfer-Encoding: binary");
    41. // нужно сделать подсчет размера файла его пути
    42. header("Content-Length: ".filesize($filename));
    43. readfile("$filename");
    44. exit();
    45. ?>
    Могу получить файл через ajax. Но как его потом открыть в новой вкладке?
     
  2. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.548
    Симпатии:
    1.754
    Авторизация какая, на сессиях? Если на сессиях, просто давайте ссылку и не морочьте себе голову. Если на токенах, и кука не ставится - тогда чуть попотеть надо. Можно через https://developer.mozilla.org/ru/docs/Web/API/URL/createObjectURL
     
  3. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Авторизация на сессиях.
    Скрипт парсит запрос и собирает страничку. Как мне пропустить прямую ссылку на файл?
     
  4. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.548
    Симпатии:
    1.754
    Не на файл прямую ссылку, а на ваш скрипт. Он же гетом принимает то, что надо. Значит может быть в урле. А куку браузер всё равно отправит при запросе, так что никуда сессия не денется.
     
  5. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    У меня получается открыть новую вкладку, запросить файл, на сервере прочитать файл с диска и послать в браузер. На браузере я его получаю и обрабатываю так:
    Код (Javascript):
    1. function onFilesLoaded(blob) {
    2.     obj_url = URL.createObjectURL(blob);
    3.     const iframe = document.getElementById('viewer');
    4.     iframe.setAttribute('src', obj_url);
    5.     URL.revokeObjectURL(obj_url);
    6. }
    Но вместо открытия файла во фрейме, он скачивается на диск. Как мне его убедить открыться для просмотра?
     
  6. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Я поковырялся еще. В предыдущем сообщении брехня. Все не так. На самом деле в строчке
    Код (Text):
    1. obj_url = URL.createObjectURL(blob);
    Выпадает ошибка.
    Uncaught TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided.
    Дальше все не идет. Прямо перед этой строкой переменная blob имеет значение
    ����JFIFHH��C и так далее. Это у меня картинка jpg. Если ее записать на диск, то она прекрасно открывается.
     
  7. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.548
    Симпатии:
    1.754
    На MDN нету "брехни". Значит у вас очень старый браузер, это новая фитча достаточно, на MDN есть описание, какие браузеры её поддерживают и с какими оговорками.
    --- Добавлено ---
    Ещё раз - если авторизация на сессиях, то всё это вообще не нужно. При запросе файла сессионная кука так же будет отправлена, и php её распознает
     
    #7 mkramer, 20 авг 2020
    Последнее редактирование: 20 авг 2020
  8. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Брехня не на MDN, a у меня в посте.

    Моя задача вывести на новой вкладке содержимое файла.
    Я сделал просто тэги <embed> и <object>. В этом случае картинки прекрасно отображаются. Но другие файлы: pdf, txt, и т.п. не отображаются на странице, а скачиваются на диск.

    Я попробовал получить фал аяксом и потом его вывести через URL.createObjectURL(). В этом случае просто выдает ошибку на этой строке. Uncaught TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided.

    Мой браузер
    Google Chrome
    Последняя версия Google Chrome уже установлена
    Версия 84.0.4147.135 (Официальная сборка), (64 бит)

    Я не настоящий сварщик. Вы мне твердите про какие-то куки. Я про куки ничего не знаю. Мне надо просто вывести файл на страничке.
     
  9. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.548
    Симпатии:
    1.754
    Наймите настоящего
     
  10. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Сделал на страничке просто ссылку на свой pdf. Все равно по ссылке скачивает, а не открывает в браузере.
     
  11. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Поставил на страничке рядом две ссылки
    Код (Text):
    1. <a href="<?= $src ?>">my link</a>
    2. <a href="https://www.w3docs.com/uploads/media/default/0001/01/540cb75550adf33f281f29132dddd14fded85bfc.pdf">w3docs</a>
    С сайта w3docs по ссылке открывается документ в браузере.
    С моего сайта начинается скачивание на диск.
    Ссылка $src формируется в таком виде https://mysite.com/files/show/file.pdf
    На сервере скрипт по адресу files.php функцией show() считывает соответствующий файл из специального каталога и отправляет тем способом, какой описан в первом посте.
    В чем может быть проблема?
    Может быть как-то по-другому надо файл отправлять с сервера в браузер?
     
  12. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.787
    Симпатии:
    646
    Браузеры не обязаны открывать pdf. А вообще смотрите в сторону снабжения ваших «файлов» соотв. ContentType-заголовком.
    --- Добавлено ---
    Mля, «Content-Disposition: attachment;» впендюрили. Лучше, правда, обратитесь к кому-то. А то есть риск слетать на Луну, из-за того что нифига не сечете в коде.
     
  13. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Я его не впендюрвал, я взял целый франмент кода из интернета. Когда мне указали на эту строчку, я с ней разобрался, и теперь все в порядке. Спасибо.
     
  14. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.787
    Симпатии:
    646
    Ну-ну. Может, поумнеете, когда поломают это дырявое корыто.
     
  15. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Мы все учимся. Надеюсь, с вашей помощью я поумнею быстрее, чем случится что-то плохое. Спасибо за помощь. Можете указать на другие проблемные строки в этом корыте?
     
  16. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.787
    Симпатии:
    646
    Начните с первой ;)

    И чтобы открыть статик файл в отдельной вкладке, нужно к тегу ссылки приписать target=_blank и все. Ну, может еще доопределить неизвестные серверу типы файлов, хотя я бы этим не стал заниматься, т.к. браузер все равно скорее всего их проигнорит.
     
  17. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    _blank я, разумеется, добавил. Цитата кода не моя, это фрагмент из интернета, который я переделываю для себя.
     
  18. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.787
    Симпатии:
    646
    Я понял, что код не ваш. Но от этого он не перестает быть кривым.

    И главное вы так и не написали, нафига он вообще нужен.
     
  19. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Я внимательно слушаю все замечания по поводу кривизны этого кода и исправляю. Спасибо за помощь. Скажите, что еще здесь плохо.
    Я уже два раза написал, зачем он нужен. Напишу третий.
    На сервере лежат файлы, загруженные пользователем. По нажатию кнопки тот или иной файл, должен открыться в новой вкладке браузера, чтобы пользователь ознакомился с его содержимым.
    Цель достигнута для картинок и pdf. Как я понимаю открыть doc или xls невозможно. Использование google docs приведет к открытию содержимого для неопределенного круга лиц, что неприемлемо.
    Доступных библиотек для просмотра таких файлов в браузере не существует.
    Так что в плане функциональности я остановился, а вот замечания по безопасности и общему состоянию кода с удовольствием принимаю.
    Где еще код кривой?
     
  20. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.787
    Симпатии:
    646
    Сервер сам умеет отдавать статик файлы. Главное ему в этом не мешать.

    Дырявый – это значит небезопасный. Небезопасность заключается в том, что любой пользователь может прочитать файлы, которые явно для этого не предназначены.
     
  21. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Чтобы отдать файлы, мы должны иметь ссылку на файл. Пользователь не имеет прямую ссылку. Его запрос содержит имя файла, а мой скрипт на сервере получает запрос и отдает файл. Только сервер знает, в какой папке лежит файл, пользователь не знает. Что нужно сделать, чтобы не мешать серверу отдать такой файл?
    Каждый запрос проверяется скриптом на текущего пользователя сессии. Если у пользователя нет права на файл, он его не получит. Как может любой пользователь прочитать чужой файл в моем случае?
    Спасибо.
     
  22. Drunkenmunky

    Drunkenmunky Активный пользователь

    С нами с:
    12 авг 2020
    Сообщения:
    1.476
    Симпатии:
    281
    http://htmlbook.ru/html/form/target
     
  23. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.787
    Симпатии:
    646
    Редирект.

    Про сессии в теме не было речи. И я не об этом. Если вы будете использовать этот код, авторизованный пользователь сможет прочитать программные файлы, файлы др. пользователей и т.п. И в любом случае в реале никто тело (более-менее крупного) файла пыхом не отдает. Для этого есть псевдозаголовки, обрабатываемые самим сервером (его модулями).
     
  24. Nemoj

    Nemoj Новичок

    С нами с:
    14 авг 2020
    Сообщения:
    30
    Симпатии:
    0
    Редирект - это так?
    Код (Text):
    1. header('Location: http://mysite/folder/file.pdf');
    Когда я использую эту функцию, запрос перехватывает мой маршрутизатор, т.е. возвращаюсь в PHP. Или я неправильно понимаю ваше предложение?
    Можете ткнуть меня носом в пример, как в реале отдают файлы не пыхом?
    Спасибо.
     
  25. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.787
    Симпатии:
    646
    Перед запуском фронта обычно ставится условие «если не файл» и т.п.

    Есть псевдозаголовки вроде X-Sendfile.
    --- Добавлено ---
    Для «Спасибо» есть спец. кнопка.
     
    Nemoj нравится это.