Ответ 1
Из ответа Заставить браузер сохранять файл после нажатия ссылки:
<a href="path/to/file" download>Click here to download</a>
У меня на моем веб-сайте есть каталоги большого размера pdf, и мне нужно связать их как загрузку. Когда я googled, я нашел такую вещь, отмеченную ниже. Он должен открыть всплывающее окно Сохранить как... ". Нажмите
<head>
<meta name="content-disposition" content="inline; filename=filename.pdf">
...
но он не работает:/когда я ссылаюсь на файл, как показано ниже, он просто ссылается на файл и пытается открыть файл.
<a href="filename.pdf" title="Filie Name">File name</a>
ОБНОВЛЕНИЕ (согласно ответам ниже):
Как я вижу, для этого нет 100% -ного надежного кросс-браузерного решения. Вероятно, наилучшим способом является использование одной из перечисленных ниже веб-сервисов и предоставление ссылки для скачивания...
Из ответа Заставить браузер сохранять файл после нажатия ссылки:
<a href="path/to/file" download>Click here to download</a>
<a href="file link" download target="_blank">Click here to download</a>
Он работает для меня в Firefox и Chrome.
Метатеги не являются надежным способом достижения этого результата. Как правило, вы даже не должны этого делать - он должен быть предоставлен пользователю/пользовательскому агенту, чтобы решить, что делать с предоставленным вами контентом. Пользователь всегда может заставить свой браузер загружать файл, если захочет.
Если вы все еще хотите заставить браузер загружать файл, измените HTTP-заголовки напрямую. Вот пример кода PHP:
$path = "path/to/file.pdf";
$filename = "file.pdf";
header('Content-Transfer-Encoding: binary'); // For Gecko browsers mainly
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT');
header('Accept-Ranges: bytes'); // Allow support for download resume
header('Content-Length: ' . filesize($path)); // File size
header('Content-Encoding: none');
header('Content-Type: application/pdf'); // Change the mime type if the file is not PDF
header('Content-Disposition: attachment; filename=' . $filename); // Make the browser display the Save As dialog
readfile($path); // This is necessary in order to get it to actually download the file, otherwise it will be 0Kb
Обратите внимание, что это просто расширение HTTP-протокола; некоторые браузеры могут его игнорировать.
Это действительно старая нить, на которую я наткнулся, поэтому я уверен, что все это было выяснено. Имел эту же проблему и нашел решение, которое до сих пор отлично работало. Вы поместите следующий код в свой файл .htaccess:
<FilesMatch "\.(?i:pdf)$">
ForceType application/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
A действительно простой способ достичь этого, без использования внешних загрузочных сайтов или модификаций заголовков и т.д. - просто создать ZIP файл с PDF внутри и напрямую связать его с ZIP файлом. Это ВСЕГДА запускает диалог "Сохранить/Открыть", и для людей все равно легко дважды щелкнуть окна PDF, запускается программа, связанная с запуском .zip.
Отличный вопрос, я тоже искал ответ, так как большинство встроенных в PDF плагинов PDF забирают sooo, чтобы отображать что угодно (и часто будут зависать в браузере во время загрузки PDF файла).
Как правило, это происходит, потому что некоторые настройки браузеров или плагины напрямую открывают PDF в том же окне, что и простая веб-страница. Это может вам помочь. Я сделал это в PHP несколько лет назад. Но в настоящее время я не работаю на этой платформе.
<?php
if (isset($_GET['file'])) {
$file = $_GET['file'] ;
if (file_exists($file) && is_readable($file) && preg_match('/\.pdf$/',$file)) {
header('Content-type: application/pdf');
header("Content-Disposition: attachment; filename=\"$file\"");
readfile($file);
}
} else {
header("HTTP/1.0 404 Not Found");
echo "<h1>Error 404: File Not Found: <br /><em>$file</em></h1>";
}
?>
Сохраните выше, как download.php
Сохраните этот маленький фрагмент в виде файла PHP где-то на вашем сервере, и вы можете использовать его, чтобы сделать загрузку файла в браузере, а не отображать напрямую. Если вы хотите обслуживать файлы, отличные от PDF, удалите или отредактируйте строку 5.
Вы можете использовать его так:
Добавьте в свой HTML файл следующую ссылку.
<a href="download.php?file=my_pdf_file.pdf">Download the cool PDF.</a>
Ссылка из: Этот блог
Я нашел очень простое решение для firefox (работает только с относительным, а не прямым href): add type = "application/octet-stream"
<a href="./file.pdf" id='example' type="application/octet-stream">Example</a>
Попробуйте добавить эту строку к файлу .htaccess.
AddType application/octet-stream .pdf
Очень простой способ сделать это, если вам нужно принудительно загрузить одну ссылку на вашей странице, заключается в использовании атрибута загрузки HTML5 в href-link.
Смотрите: http://davidwalsh.name/download-attribute
с этим вы можете переименовать файл, который будет загружен пользователем, и в то же время он заставит загрузить.
Была дискуссия о том, является ли это хорошей практикой или нет, но в моем случае у меня есть встроенный просмотрщик для pdf файла, и зритель не предлагает ссылку для загрузки, поэтому я должен предоставить его отдельно. Здесь я хочу убедиться, что пользователь не получает pdf файл, открытый в веб-браузере, что будет путать.
Это не обязательно откроет диалоговое окно сохранения в виде, но загрузит ссылку прямо в заданное место загрузки. И, конечно, если вы делаете сайт для кого-то другого и нуждаетесь в том, чтобы они записывали атрибуты вручную в свои ссылки, вероятно, это плохая идея, но если есть способ получить атрибут в ссылках, это может быть легким решением.
Решение на стороне сервера более совместимо, пока атрибут "загрузка" не будет реализован во всех браузерах.
Один пример python может быть настраиваемым обработчиком запросов HTTP для филереста. Ссылки, указывающие на filestore, генерируются следующим образом:
http://www.myfilestore.com/filestore/13/130787e71/download_as/desiredName.pdf
вот код:
class HTTPFilestoreHandler(SimpleHTTPRequestHandler):
def __init__(self, fs_path, *args):
self.fs_path = fs_path # filestore path
SimpleHTTPRequestHandler.__init__(self, *args)
def send_head(self):
# overwrite SimpleHTTPRequestHandler.send_head to force download name
path = self.path
get_index = (path == '/')
self.log_message("path: %s" % path)
if '/download_as/' in path:
p_parts = path.split('/download_as/')
assert len(p_parts) == 2, 'Bad download link:' + path
path, download_as = p_parts
path = self.translate_path(path )
f = None
if os.path.isdir(path):
if not self.path.endswith('/'):
# redirect browser - doing basically what apache does
self.send_response(301)
self.send_header("Location", self.path + "/")
self.end_headers()
return None
else:
return self.list_directory(path)
ctype = self.guess_type(path)
try:
f = open(path, 'rb')
except IOError:
self.send_error(404, "File not found")
return None
self.send_response(200)
self.send_header("Content-type", ctype)
fs = os.fstat(f.fileno())
self.send_header("Expires", '0')
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.send_header("Cache-Control", 'must-revalidate, post-check=0, pre-check=0')
self.send_header("Content-Transfer-Encoding", 'binary')
if download_as:
self.send_header("Content-Disposition", 'attachment; filename="%s"' % download_as)
self.send_header("Content-Length", str(fs[6]))
self.send_header("Connection", 'close')
self.end_headers()
return f
class HTTPFilestoreServer:
def __init__(self, fs_path, server_address):
def handler(*args):
newHandler = HTTPFilestoreHandler(fs_path, *args)
newHandler.protocol_version = "HTTP/1.0"
self.server = BaseHTTPServer.HTTPServer(server_address, handler)
def serve_forever(self, *args):
self.server.serve_forever(*args)
def start_server(fs_path, ip_address, port):
server_address = (ip_address, port)
httpd = HTTPFilestoreServer(fs_path, server_address)
sa = httpd.server.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()
просто введите код ниже в файл .htaccess
AddType application/octet-stream .csv
AddType application/octet-stream .xls
AddType application/octet-stream .doc
AddType application/octet-stream .avi
AddType application/octet-stream .mpg
AddType application/octet-stream .mov
AddType application/octet-stream .pdf
или вы также можете сделать трюк с помощью javascript
element.setAttribute( 'download', whatever_string_you_want );
Если у вас есть плагин в браузере, который знает, как открыть PDF файл, он откроется напрямую. Как в случае с изображениями и содержимым html. Таким образом, альтернативный подход заключается не в том, чтобы отправить ваш тип mime в ответ таким образом, браузер никогда не узнает, какой плагин должен его открыть. Следовательно, это даст вам диалоговое окно "Сохранить открытие".
После имени файла в коде HTML я добавляю ?forcedownload=1
Это был самый простой способ вызвать диалоговое окно для сохранения или загрузки.
У меня была очень похожая проблема с добавленной проблемой, что мне нужно было создать ссылки для загрузки файлов внутри zipFile. Сначала я попытался создать временный файл, а затем предоставил ссылку на временный файл, но обнаружил, что некоторые браузеры просто отображают содержимое (файл Excel CSV), а не предлагают загрузить. В конце концов я нашел решение с помощью сервлета. Он работает как на tomcat, так и на стеклянной рыбке, и я пробовал его на IE10 и хром.
сервлет принимает в качестве ввода полное имя пути в zip файл и имя файла внутри zip, который должен быть downlaoded.
Внутри моего JSP файла у меня есть таблица, отображающая все файлы внутри zip, со ссылками, которые говорят: onclick='download?zip=<%=zip%>&csv=<%=csv%>'
Код сервлета находится в файле download.java:
package myServlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.zip.*;
import java.util.*;
// Extend HttpServlet class
public class download extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
PrintWriter out = response.getWriter(); // now we can write to the client
String filename=request.getParameter("csv");
String zipfile=request.getParameter("zip");
String aLine="";
response.setContentType("application/x-download");
response.setHeader( "Content-Disposition", "attachment; filename=" + filename ); // force 'save-as'
ZipFile zip = new ZipFile(zipfile);
for (Enumeration e = zip.entries(); e.hasMoreElements();) {
ZipEntry entry = (ZipEntry) e.nextElement();
if(entry.toString().equals(filename)) {
InputStream is = zip.getInputStream(entry);
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"), 65536);
while ((aLine=br.readLine())!=null) {
out.println(aLine);
}
is.close();
break;
}
}
}
}
Для компиляции на tomcat вам понадобится classpath для включения tomcat\lib\servlet-api.jar или на стеклянную рыбку: glassfish\lib\j2ee.jar но каждый из них будет работать на обоих. Вам также необходимо установить сервлет в web.xml.
с большим PDF браузером зависает в Mozilla Tools > Параметры > Приложения > затем рядом с типом содержимого Adobe Acrobat document в раскрывающемся списке "Действие" выберите "Всегда спрашивать". это не сработало для меня, так что получилось:
Инструменты > Дополнения > Adobe Acrobat (плагин Adobe pdf для Firefox) > ОТКЛЮЧЕН теперь я ВОЗМОЖНО скачать электронные книги!