Разработка оффлайн-браузера, способного сохранять HTML-страницы со всем их содержимым из Сети - дипломная работа готовая

ООО "Диплом777"

8:00–20:00 Ежедневно

Никольская, д. 10, оф. 118

Дипломная работа на тему Разработка оффлайн-браузера, способного сохранять HTML-страницы со всем их содержимым из Сети

Введение

Браузер (Веб-обозреватель) (от англ. Web browser) – программное обеспечение для просмотра веб-сайтов, то есть для запроса веб-страниц (преимущественно из Сети), их обработки, вывода и перехода от одной страницы к другой.

Часть браузеров поддерживают кроме онлайн-режима, когда браузер пытается получить страницы с веб-сервера, оффлайн-режим, при котором можно просматривать сохранённые копии ранее посещённых страниц. Оффлайн-режим полезен, когда по какой-либо причине нет соединения с интернетом. Страницы либо неявно сохраняются в кэше браузера при посещении веб-сервера, либо браузер специально настраивается на сохранение и поддержание локальных копий определённых сайтов. Копии обновляются либо при восстановлении соединения, либо по расписанию.

Целью задачи данной работы является создание оффлайн-браузера, способного сохранять HTML страницы со всем их содержимым из Сети. Одной из особенностей программы будет загрузка страниц с заданным уровнем вложенности, то есть с заданным количеством переходов по ссылкам «вглубь». Таким образом, при необходимости, можно будет сохранить не одну страницу, а все страницы, к которым мы можем получить доступ, переходя по ссылке с предыдущей. В итоге у нас будет возможность сохранять весь сайт целиком.

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

Ниже приведена схема, показывающая принцип работы программы:

1. HTML

1.1 Общие сведения по HTML

HTML (HyperText Mark-up Language/язык гипертекстовой разметки) – это язык, который позволяет представлять информацию в Internet. То, что вы видите при просмотре страницы в Internet, это интерпретация вашим браузером HTML-текста.

· Hyper противоположно linear/построчно. Ранее компьютерные программы работали построчно: программа выполняла одну строку, затем переходила к выполнению следующей, и т.д. Но HTML работает по-иному – вы можете перейти куда и когда захотите.

· Text – собственно, текст.

· Mark-up – это разметка, то, что вы можете делать с текстом. Размечается текст так же, как это делается в текстовых редакторах: выставление заголовка, списков, выделение текста жирным шрифтом и т.д.

· Language – это язык HTML. В нём используется много английских слов, что заметно облегчает работу с ним.

Изначально язык HTML был задуман и создан как средство структурирования и форматирования документов без их привязки к средствам воспроизведения (отображения). В идеале, текст с разметкой HTML должен был без стилистических и структурных искажений воспроизводиться на оборудовании с различной технической оснащённостью. Однако современное применение HTML очень далеко от его изначальной задачи.

1.2 Структура HTMLдокумента

HTML – теговый язык разметки документов. Любой документ на языке HTML представляет собой набор элементов, причём начало и конец каждого элемента обозначается специальными пометками – тегами. Элементы могут быть пустыми, то есть не содержащими никакого текста и других данных (например, тег перевода строки <br />). В этом случае обычно не указывается закрывающий тег. Кроме того, элементы могут иметь атрибуты, определяющие какие-либо их свойства (например, размер шрифта для элемента font). Атрибуты указываются в открывающем теге.

Тэги – это метки, которые используются для указания браузеру, как он должен показывать web-сайт.

Все тэги имеют одинаковый формат: они начинаются знаком «<» и заканчиваются знаком «>».

Обычно имеются два тэга – открывающий: <html> и закрывающий: </html>. Различие в том, что в закрывающем имеется слеш «/».

Всё содержимое, помещённое между открывающим и закрывающим тэгами, является содержимым тэга.

Но из каждого правила есть исключения – в HTML также имеются тэги, которые являются и открывающими, и закрывающими. Эти тэги не содержат текста, а являются метками, например, перенос строки выглядит так: <br />.

Примеры использования тегов:

Пример 1:

Тэг <b> информирует браузер, что весь текст между <b> и </b> должен быть напечатан жирным шрифтом. («b» это сокращение для «bold») То есть

<b>This text must be bold.</b>

будет выглядеть при просмотре в браузере следующим образом:

This text must be bold.

Пример 2:

Тэги <p>, <h2>, <h3>, <h4>, <h5> и <h6> указывают браузеру создавать заголовки (h для «heading»), где <p> это заголовок первого уровня самый крупный шрифт, <h2> заголовок второго уровня шрифт меньшего размера, и <h6> заголовок шестого уровня самого низкого в этой иерархии, и самый маленький шрифт.

<p>Это заголовок</p>

<h2>Это подзаголовок</h2>

будет выглядеть в браузере:

Это заголовок

Это подзаголовок

Большинству браузеров безразлично, в каком регистре введены буквы тэгов. <HTML>, <html> или <HtMl> обычно даёт одинаковый результат. Однако корректным будет нижний регистр.

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

Структура документа HTML выглядит следующим образом:

<html>

<head>

<title></title>

</head>

<body>

</body>

</html>

1.3 Теги A, IMG, Script и Style

Тег a является одним из важных элементов HTML и предназначен для создания ссылок. В зависимости от присутствия атрибутов name или href тег <a> устанавливает ссылку или якорь. Якорем называется закладка внутри страницы, которую можно указать в качестве цели ссылки. При использовании ссылки, которая указывает на якорь, происходит переход к закладке внутри веб-страницы.

Синтаксис

<a href= «URL»>…</a>

<a name= «идентификатор»>…</a>

Тег img, как один из самых основных в HTML, нужен для вставки изображения на страницу. Он имеет такой синтаксис:
<img src= «путь_к_картинке»>

Тег может иметь пути, как внутренний (например, к картинке в папке), так и внешний (указанный ссылкой на изображение в Сети).

Для тега img рекомендуется прописывать описание (всплывающую подсказку) вида:

<img src= «blog.jpg» alt= «Блог» title= «Блог»>

Такое указание описаний позволит дать поисковым системам больше информации об изображении, и, соответственно, ваша картинка будет иметь позиции гораздо выше при поиске картинок.

Тег script (англ. script – сценарий) – тег-контейнер, добавляет на страницу скрипт. Текст скрипта может располагаться между начальным и конечным тегами или определяется как URL файла, содержащего скрипт. Может содержаться как в секции <head>, так и в <body>

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

В случае если браузер не поддерживает скрипты, тег <script> будет проигнорирован. Все, что расположено между <script> и </script> будет выведено на экран, как обычный текст. Для того, чтобы этого не случилось текст скрипта обозначается, как комментарий (<! – // ->).

Тег style применяется для определения стилей элементов веб-страницы Тег <style> необходимо использовать внутри контейнера <head>. Можно задавать более чем один тег <style>.

Синтаксис:

<head>

<style type= «text/css»>

</style>

</head>

Пример:

<! DOCTYPE HTML>

<html>

<head>

<meta charset= «utf-8»>

<title>Тег STYLE</title>

<style type= «text/css»>

p {

font-size: 120%;

font-family: Verdana, Arial, Helvetica, sans-serif;

color: #333366;

}

</style>

</head>

<body>

<H1>Hello, world!</H1>

</body>

</html>

2. Используемые технологии Java

2.1 Общие сведения о Java

Java – это мощный язык программирования, разработанный в 1995 г. фирмой Sun Microsystems (в последующем приобретённой компанией Oracle) для интерактивного телевидения и управления бытовыми устройствами. Однако быстрое развитие Internet открыло другое призвание Java – создание небольших программ, называемых аплетами (applets), которые могут быть загружены Веб-браузером с сервера и исполнены на стороне клиента.

Популярность Java объясняется тем, что он имеет одно принципиальное отличие от всех остальных языков программирования. Как известно, все языки делятся на компилируемые и интерпретируемые. Программа на компилируемом языке (например, C++) перед использованием должна быть предварительно скомпилирована и собрана в загрузочный модуль в машинных кодах. Такой модуль характеризуется высокой скоростью работы, но он жестко привязан к конкретной платформе и конкретной операционной системе; для его переноса в другую среду требуется перекомпиляция всей программы. Интерпретируемые языки не требуют предварительной компиляции, программы на них исполняются интерпретатором, который читает исходный текст программы и немедленно его исполняет.

Программа на языке Java компилируется в промежуточный стандартный код, который называется байт-кодом (такие файлы имеют расширение.class). Этот код не является машинным языком какого-либо конкретного процессора, а специально создан авторами Java; его следует рассматривать как язык ассемблера виртуальной Java-машины, не имеющей физической реализации.

2.2 Описание библиотеки JSOUP, предназначенной для обработки HTML страницы

Java-библиотека jsoup предназначена для разбора HTML-страниц (парсинг), позволяя извлечь необходимые данные, используя DOM, CSS и методы в стиле jQuery.

Библиотека поддерживает спецификации HTML5 и позволяет парсить страницы, как это делают современные браузеры.

Библиотеке можно предоставить для анализа URL, файл или строку.

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

В приложении JSOUP используется для обработки HTML документа и получения ссылок на другие ресурсы из соответствующих тэгов:

Метод разбора исходного HTML документа. Считывает исходный файл, загруженный по ссылке page, и заменяет ссылки, найденные в base[href], a[href], img[src], link[href], script[src], на ссылки на загружаемые файлы. Для обработки используется библиотека Jsoup.

@param dm объект DownloadManager необходим для получения доступа к глобальному списку ссылок.

@param page ссылка на текущую страницу.

@param sourceFileName имя исходного файла.

@param destFileName имя файла, в котором исходные ссылки уже заменены на локальные.

@param charsetName кодировка исходного файла.

@return список ссылок, найденных в файле.

@see Jsoup

@see DownloadManager

@see DownloadURL

public List<DownloadURL> parseLinksInDocument (DownloadManager dm, DownloadURL page, String sourceFileName, String destFileName, String charsetName) {

try {

List<DownloadURL> pageLinks = new ArrayList<DownloadURL>();

File sourceFile = new File(sourceFileName);

// Обработка HTML файла sourceFile с кодировкой charsetName

Document doc = Jsoup.parse (sourceFile, charsetName);

// Поиск тэгов base с атрибутами href

Elements base = doc.select («base[href]»);

// Поиск тэгов a с атрибутами href

Elements links = doc.select («a[href]»);

// Поиск тэгов img с атрибутом src

Elements media = doc.select («img[src]»);

// Поиск тэгов import с атрибутом href

Elements imports = doc.select («link[href]»);

// Поиск тэгов script с атрибутом src

Elements scripts = doc.select («script[src]»);

// Для каждого тэга base

for (Element b: base) {

// Формируем абсолютную ссылку на ресурс из аттрибута href тэга

URL url = makeURL (b.attr («href»), page.getUrl());

if (url!= null) {

// Если ссылка указывает на ресурс этого же домена, заменяем на ссылку на локальный файл

if (url.getHost().equals (page.getUrl().getHost())) {

// Если ссылка указывает на ресурс на этом же домене, то добавляем ссылку для дальнейшего скачивания

if (! dm.globalInfo.contains(url) && page.getLevel() < Common.DEFAULTLEVEL) {

DownloadURL du = new DownloadURL (url, page.getLevel() + 1, null, DownloadURL.DOWNLOADING);

dm.globalInfo.addPageInfo(du);

pageLinks.add(du);

}

b.attr («href», dm.globalInfo.getSiteSaveAbsolutePath() + url.getPath());

} else {

b.attr («href», dm.globalInfo.getSiteSaveAbsolutePath() + File.separator + url.getHost() + url.getPath());

}

}

}

// Для каждого тэга img

for (Element src: media) {

// Формируем абсолютную ссылку на ресyрс из атрибута src

URL url = makeURL (src.attr («src»), page.getUrl());

if (url!= null) {

// Если ссылка на документ находящийся на том же домене, то ссылка заменяется на локальный файл

if (url.getHost().equals (page.getUrl().getHost())) {

// Если ссылка на документ того же домена, то добавляет в глобальный список ссылок для скачивания

if (! dm.globalInfo.contains(url) && page.getLevel() < Common.DEFAULTLEVEL) {

DownloadURL du = new DownloadURL (url, page.getLevel() + 1, null, DownloadURL.DOWNLOADING);

dm.globalInfo.addPageInfo(du);

pageLinks.add(du);

}

src.attr («src», dm.globalInfo.getSiteSaveAbsolutePath() + url.getPath());

} else {

src.attr («src», dm.globalInfo.getSiteSaveAbsolutePath() + File.separator + url.getHost() + url.getPath());

}

}

}

// Для каждого тэга import

for (Element link: imports) {

// Формируем абсолютную ссылку на ресyрс из атрибута href

URL url = makeURL (link.attr («href»), page.getUrl());

if (url!= null) {

// Если ссылка на документ находящийся на том же домене, то ссылка заменяется на локальный файл

if (url.getHost().equals (page.getUrl().getHost())) {

// Если ссылка на документ того же домена, то добавляет в глобальный список ссылок для скачивания

if (! dm.globalInfo.contains(url) && page.getLevel() < Common.DEFAULTLEVEL) {

DownloadURL du = new DownloadURL (url, page.getLevel() + 1, null, DownloadURL.DOWNLOADING);

dm.globalInfo.addPageInfo(du);

pageLinks.add(du);

}

link.attr («href», dm.globalInfo.getSiteSaveAbsolutePath() + url.getPath());

} else {

link.attr («href», dm.globalInfo.getSiteSaveAbsolutePath() + File.separator + url.getHost() + url.getPath());

}

}

}

// Для каждого тэга link

for (Element link: links) {

// Формируем абсолютную ссылку на ресyрс из аттрибута href

URL url = makeURL (link.attr («href»), page.getUrl());

if (url!= null) {

// Если ссылка на документ находящийся на том же домене, то ссылка заменяется на локальный файл

if (url.getHost().equals (page.getUrl().getHost())) {

// Если ссылка на документ того же домена, то добавляет в глобальный список ссылок для скачивания

if (! dm.globalInfo.contains(url) && page.getLevel() < Common.DEFAULTLEVEL) {

DownloadURL du = new DownloadURL (url, page.getLevel() + 1, null, DownloadURL.DOWNLOADING);

pageLinks.add(du);

dm.globalInfo.addPageInfo(du);

}

link.attr («href», dm.globalInfo.getSiteSaveAbsolutePath() + url.getPath());

} else {

link.attr («href», dm.globalInfo.getSiteSaveAbsolutePath() + File.separator + url.getHost() + url.getPath());

}

}

}

// Для каждого тэга script

for (Element script: scripts) {

// Формируем абсолютную ссылку на ресyрс из атрибута href

URL url = makeURL (script.attr («src»), page.getUrl());

if (url!= null) {

// Если ссылка на документ находящийся на том же домене, то ссылка заменяется на локальный файл

if (url.getHost().equals (page.getUrl().getHost())) {

// Если ссылка на документ того же домена, то добавляет в глобальный список ссылок для скачивания

if (! dm.globalInfo.contains(url) && page.getLevel() < Common.DEFAULTLEVEL) {

DownloadURL du = new DownloadURL (url, page.getLevel() + 1, null, DownloadURL.DOWNLOADING);

pageLinks.add(du);

dm.globalInfo.addPageInfo(du);

}

script.attr («src», dm.globalInfo.getSiteSaveAbsolutePath() + url.getPath());

} else {

script.attr («src», dm.globalInfo.getSiteSaveAbsolutePath() + File.separator + url.getHost() + url.getPath());

}

}

}

File dest = new File(destFileName);

if (! sourceFileName.equals(destFileName))

if (dest.delete())

FileUtils.moveFile (sourceFile, new File(destFileName));

// if (sourceFile.delete())

PrintWriter pw = new PrintWriter(destFileName);

pw.write (doc.html());

pw.flush();

pw.close();

return pageLinks;

} catch (IOException ex) {

Logger.getLogger (Parser.class.getName()).log (Level.SEVERE, null, ex);

}

return null;

}

2.3 Многопоточность в Java

браузер программа сайт тег

Наиболее очевидная область применения многопоточности – это программирование интерфейсов. Многопоточность незаменима тогда, когда необходимо, чтобы графический интерфейс продолжал отзываться на действия пользователя во время выполнения некоторой обработки информации. Например, поток, отвечающий за интерфейс, может ждать завершения другого потока, загружающего файл из интернета, и в это время выводить некоторую анимацию или обновлять прогресс-бар. Кроме того он может остановить поток загружающий файл, если была нажата кнопка «отмена».

Еще одна популярная и, пожалуй, одна из самых распространённых областей применения многопоточности – игры. В играх различные потоки могут отвечать за работу с сетью, анимацию, расчет физики и т.д.

Рассмотрим пример реализации многопоточности из нашей программы. Приложение использует механизм многопоточности для параллельного скачивания файлов. Для каждой загрузки открывается новый поток загрузки. Код метода run() потока, выполняющего непосредственную загрузку файлов:

Метод запуска потока загрузки, внутри него создается HTTP соединение с необходимыми параметрами и запускается скачивание.

public void run() {

RandomAccessFile file = null;

InputStream stream = null;

// Создает класс обработки файлов

Parser parser = new Parser();

DefaultHttpClient httpclient = new DefaultHttpClient();

try {

// Добавление перехвата запроса и ответа для правильной обработки

// файлов, которые сжаты методом GZIP

httpclient.addRequestInterceptor (new HttpRequestInterceptor() {

public void process (

final HttpRequest request,

final HttpContext context) throws HttpException, IOException {

if (! request.containsHeader («Accept-Encoding»)) {

request.addHeader («Accept-Encoding», «gzip»);

}

}

});

httpclient.addResponseInterceptor (new HttpResponseInterceptor() {

public void process (

final HttpResponse response,

final HttpContext context) throws HttpException, IOException {

HttpEntity entity = response.getEntity();

if (entity!= null) {

Header ceheader = entity.getContentEncoding();

if (ceheader!= null) {

HeaderElement[] codecs = ceheader.getElements();

for (int i = 0; i < codecs.length; i++) {

if (codecs[i].getName().equalsIgnoreCase («gzip»)) {

response.setEntity (

new GzipDecompressingEntity (response.getEntity()));

return;

}

}

}

}

}

});

// Формирование запроса на WEB-сервер с необходимыми параметрами для

// возможности докачки файлов

HttpGet httpget = new HttpGet (this.url.toString());

httpget.addHeader («Range»,

«bytes=» + downloaded +» -»);

httpget.addHeader («Accept», «text/html, application/xhtml+xml, application/xml; q=0.9,*/*; q=0.8»);

httpget.addHeader («Pragma», «no-cache»);

httpget.addHeader («User-Agent», Common.USERAGENT);

HttpResponse response = httpclient.execute(httpget);

// Проверка, что ответ сервера говорит об успешной обработке запроса

if (response.getStatusLine().getStatusCode() / 100!= 2) {

error();

}

// Вычисление оставшейся части документа для дозагрузки

long contentLength = -1;

if (response.getHeaders («Content-Length»).length == 0)

error();

else {

contentLength = Long.valueOf (response.getHeaders («Content-Length») [0].getValue());

if (contentLength < 1) {

error();

}

}

if (size == -1) {

size = contentLength;

stateChanged();

}

String fullFileName;

String tempFileName;

if (getFileName(url.getUrl()).length() < 2)

fullFileName = downloadManager.globalInfo.getSiteSaveTempPath() + File.separator + Common.getTempfileName («index.html»);

else

fullFileName = downloadManager.globalInfo.getSiteSaveTempPath() + File.separator + Common.getTempfileName (getFileName(url.getUrl()));

// Проверка, необходим ли разбор файла на наличие вложенных ссылок

if (Parser.isParseable (response.getEntity().getContentType().getValue())) {

tempFileName = fullFileName +».tmp»;

} else {

tempFileName = fullFileName;

}

url.setTempFileName(fullFileName);

file = new RandomAccessFile (tempFileName, «rw»);

file.seek(downloaded);

stream = response.getEntity().getContent();

// Скачивание файла

while (status == DOWNLOADING) {

byte buffer[] = new byte [MAX_BUFFER_SIZE];

// Чтение данных из потока

int read = stream.read(buffer);

if (read <= 0)

break;

// Запись данных в файл

file.write (buffer, 0, read);

downloaded += read;

stateChanged();

}

// Выполнение действий после успешного скачивания файла

if (status == DOWNLOADING) {

status = COMPLETE;

url.setStatus (DownloadURL.COMPLETE);

downloadManager.globalInfo.incrementCompletedPagesNumber();

String contentType = response.getEntity().getContentType().getValue();

if (url.getLevel() <= Common.DEFAULTLEVEL && Parser.isParseable(contentType)) {

List<DownloadURL> descendantPages = null;

System.out.println(contentType);

if (contentType.contains («text/html»))

descendantPages = parser.parseLinksInDocument (downloadManager, url, tempFileName, fullFileName, Charset.defaultCharset().name());

else if (contentType.contains («text/css»))

descendantPages = parser.parseCSSDocument (url, tempFileName, fullFileName);

for (DownloadURL u: descendantPages) {

//System.out.println(«{» + u.getLevel() +»}» + u.getUrl());

Thread.sleep(100);

downloadManager.globalInfo.incrementPagesNumber();

tableModel.addDownload (new Download (downloadManager, u, tableModel));

}

url.setNoDescendants(true);

} else

url.setNoDescendants(true);

stateChanged();

}

} catch (Exception e) {

e.printStackTrace();

error();

} finally {

// Закрытие файла

if (file!= null) {

try {

file.close();

} catch (Exception e) {}

}

// Закрытие соединения с сервером

if (stream!= null) {

try {

stream.close();

} catch (Exception e) {}

}

httpclient.getConnectionManager().shutdown();

}

}

2.4 Java Swing

Первые Java программы страдали бедностью интерфейсов. Более того, создание интерфейса, который запускался бы на любой платформе, часто было сложной задачей. Однако библиотека Swing изменила все. Благодаря Swing ваши приложения могут прекрасно выглядеть и прекрасно работать и под Windows, и под Linux, и на любой другой платформе.

Swing это набор для создания богатого графического интерфейса пользователя (GUI) для Java программ и апплетов. Вот основные преимущества использования библиотеки Swing перед её аналогами:

· богатый набор интерфейсных примитивов

· настраивающийся внешний вид на различных платформах (look and feel)

· раздельная архитектура модель-вид (model-view)

· встроенная поддержка HTML

Создание сложного GUI при помощи AWT (Abstract Window Toolkit – это первая оконная подсистема) практически невозможно, поскольку в AWT нет основных интерфейсных примитивов. Swing же предоставляет этот набор и не только. Он также делает создание GUI более легким за счет применения набора настраиваемых границ (Borders) и менеджеров размещения (LayoutManagers).

Практически все компоненты Swing начинаются с главенствующей буквы J (JFrame, JTable, JMenu). Названия всех компонентов очевидны, и сходны с теми, которые использовались в AWT. К примеру, если в AWT в роли окна верхнего уровня использовалось Frame, в Swing используется в аналогичной роли JFrame. Краткое описание некоторых важных элементов, которых не имела в своем активе AWT приведены ниже.

JInternalFrame

Окно, существующее внутри другого окна верхнего уровня, например в JFrame.

JProgressBar

Строка, отображающая процесс проистечения какого-то события, например процесс загрузки.

JSlider

«Ползунок», позволяющий пользователю выбирать предел отображения величин.

JTable

Компонент, представляющий данные в виде таблиц.

JTree

Компонент, представляющий данные в иерархическом виде.

SWING используется для построения графического пользовательского интерфейса приложения. Графические элементы интерфейса создаются в конструкторе класса DownloadManager:

Конструктор класса, вызывается при запуске приложения. Он создает элементы графического интерфейса:

public DownloadManager() {

// Установка заголовка окна

setTitle («Offline browser»);

// Размер окна

setSize (640, 480);

// Обработка события закрытия окна

addWindowListener (new WindowAdapter() {

public void windowClosing (WindowEvent e) {

actionExit();

}

});

// Добавление меню

JMenuBar menuBar = new JMenuBar();

JMenu fileMenu = new JMenu («Файл»);

fileMenu.setMnemonic (KeyEvent.VK_F);

JMenuItem fileExitMenuItem = new JMenuItem («Выход»,

KeyEvent.VK_X);

fileExitMenuItem.addActionListener (new ActionListener() {

public void actionPerformed (ActionEvent e) {

actionExit();

}

});

fileMenu.add(fileExitMenuItem);

menuBar.add(fileMenu);

setJMenuBar(menuBar);

// Верхняя панель с кнопками для ввода ссылки для загрузки

JPanel addPanel = new JPanel (new FlowLayout());

addTextField = new JTextField(30);

addPanel.add(addTextField);

JButton addButton = new JButton («Загрузить»);

addButton.addActionListener (new ActionListener() {

public void actionPerformed (ActionEvent e) {

actionAdd();

}

});

addPanel.add(addButton);

JLabel labelChooseDir = new JLabel («Путь сохранения файлов»);

addPanel.add(labelChooseDir);

JTextField dirField = new JTextField();

addPanel.add(dirField);

// Таблица для отображения статуса загружаемых файлов

tableModel = new DownloadsTableModel();

table = new JTable(tableModel);

table.getSelectionModel().addListSelectionListener (new

ListSelectionListener() {

public void valueChanged (ListSelectionEvent e) {

tableSelectionChanged();

}

});

table.setSelectionMode (ListSelectionModel.SINGLE_SELECTION);

ProgressRenderer renderer = new ProgressRenderer (0, 100);

renderer.setStringPainted(true); // show progress text

table.setDefaultRenderer (JProgressBar.class, renderer);

table.setRowHeight(

(int) renderer.getPreferredSize().getHeight());

// Панель для отображения таблицы загрузок

JPanel downloadsPanel = new JPanel();

downloadsPanel.setBorder (

BorderFactory.createTitledBorder («Загрузки»));

downloadsPanel.setLayout (new BorderLayout());

downloadsPanel.add (new JScrollPane(table),

BorderLayout.CENTER);

// Нижняя панель с кнопками управления загрузками

JPanel buttonsPanel = new JPanel();

pauseButton = new JButton («Пауза»);

pauseButton.addActionListener (new ActionListener() {

public void actionPerformed (ActionEvent e) {

actionPause();

}

});

pauseButton.setEnabled(false);

buttonsPanel.add(pauseButton);

resumeButton = new JButton («Возобновление»);

resumeButton.addActionListener (new ActionListener() {

public void actionPerformed (ActionEvent e) {

actionResume();

}

});

resumeButton.setEnabled(false);

buttonsPanel.add(resumeButton);

cancelButton = new JButton («Отмена»);

cancelButton.addActionListener (new ActionListener() {

public void actionPerformed (ActionEvent e) {

actionCancel();

}

});

cancelButton.setEnabled(false);

buttonsPanel.add(cancelButton);

clearButton = new JButton («Очистка»);

clearButton.addActionListener (new ActionListener() {

public void actionPerformed (ActionEvent e) {

actionClear();

}

});

clearButton.setEnabled(false);

buttonsPanel.add(clearButton);

// Добавление панелей в окно приложения

getContentPane().setLayout (new BorderLayout());

getContentPane().add (addPanel, BorderLayout.NORTH);

getContentPane().add (downloadsPanel, BorderLayout.CENTER);

getContentPane().add (buttonsPanel, BorderLayout.SOUTH);

}

3. Реализация программы

3.1 Описание программы

Приложение представляет собой менеджер загрузок с возможностью дозагрузки не полностью загруженных файлов. Перед загрузкой необходимо выбрать директорию сохранения файлов и глубину их обработки. Приложение поддерживает обработку содержащихся в файлах ссылок на другие ресурсы, что позволяет скачивать содержимое сайта с заданным уровнем вложенности. Обработка множества файлов происходит одновременно благодаря поддержке многопоточной обработки – для каждого отдельного файла открывается новый поток для скачивания.

Обработка файлов разных типов:

· HTML – файлы типа HTML разбираются на наличие в них ссылок на другие ресурсы в следующих элементах документа:

· тэг base, атрибут href,

· тэг a, атрибут href,

· тэг img, атрибут src,

· тэг link, атрибут href,

· тэг script, атрибут src.

· CSS – внутри файлов с типом CSS происходит поиск атрибутов содержащих значения типа url, указывающие на другие ресурсы.

В дальнейшем, если уровень вложенности, задаваемый перед загрузкой, не превышает уровня вложенности текущего документа, приложение докачивает файлы, на которые указывают ссылки.

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

Инструкции по использованию.

После запуска приложения открывается окно следующего вида:

Для загрузки WEB-ресурса необходимо указать следующие данные:

· Ссылку на документ, который необходимо скачать.

· Выбрать директорию на компьютере, в которую будут сохранены данные.

· Если необходимо изменить заполненный по умолчанию уровень вложенности скачиваемых документов.

· Далее после нажатия на кнопку «Загрузить» начнется загрузка документов.

После запуска загрузки вы можете непосредственно ими управлять.

При выборе загрузки становятся активными кнопки управления скачиванием:

· Кнопка «Пауза» предназначена для приостановки загрузки.

· Кнопка «Возобновление» предназначена для возобновления загрузки.

· Кнопка «Отмена» предназначена для отмены загрузки.

· Кнопка «Очистка» удаляет выбранную загрузку из таблицы.

3.2 Описание классов

Class Common

· java.lang. Object

· org.agu.fizmat.pm.offlinebrowser. Common

public class Common

extends java.lang. Object

Класс содержит общие методы и константы

· Поля класса

Модификатор и тип

Поле и описание

static java.lang. String

CONTENTTYPECSS

Content-type документа, соответствующие CSS таблице стилей

static java.lang. String

CONTENTTYPEHTML

Content-type документа, соответствующие HTML документу

static java.lang. String

CONTENTTYPEJAVASCRIPT

Content-type документа, соответствующие JavaScript файлам

static int

DEFAULTLEVEL

Уровень вложенности по умолчанию при скачивании файлов

static java.lang. String

DOWNLOADSPATH

static java.lang. String

USERAGENT

User-Agent, которым подписывает HTTP клиент при скачивании данных

· Конструкторы

· Common

publicCommon()

· Методы

· getTempfileName

public staticjava.lang. StringgetTempfileName (java.lang. Stringpage)

Метод формирует временное имя для файла из его адреса. Использует алгоритм SHA1 для получения уникальной строки

Параметры:

page – HTTP адрес файла

Возвращает:

временное имя файла

Class Download

· java.lang. Object

· java.util. Observable

· org.agu.fizmat.pm.offlinebrowser. Download

· All Implemented Interfaces:

java.lang. Runnable

public class Download

extends java.util. Observable

implements java.lang. Runnable

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

· Поля класса

Модификатор и тип данных

Имя поля и описание

static int

CANCELLED

Статус присваивается, если процесс скачивания отменен

static int

COMPLETE

Статус присваивается после удачного завершения процесса скачивания

static int

DOWNLOADING

Статус присваивается в процессе скачивания

static int

ERROR

Статус присваивается, если при скачивании произошла ошибка

static int

PAUSED

Статус присваивается после того как скачивание приостановлено

static java.lang. String[]

STATUSES

Список статусов для ссылки

· Конструкторы

· Download

Public Download (DownloadManager dm,

DownloadURL url,

DownloadsTableModel tableModel)

Конструктор класса, при создании автоматически запускается процесс скачивания документа по ссылке url

Параметры:

dm – экземпляр класса менеджера загрузки, который инициировал скачивание

url – объект класса DownloadURL, содержит ссылку для скачивания файла

tableMode – графический элемент, содержащий информацию о процессе скачивания

· Методы

· getUrl

public java.lang. String getUrl()

Метод получения строки, представляющей ссылку на документ

Возвращает:

ссылку на файл

· getSize

public long getSize()

Метод получения размера скачиваемого файла

Возвращает:

размер файла в байтах

· getProgress

public float getProgress()

Метод получения процентной доли скачанного от общего размера файла

Возвращает:

число от 0 до 100, соответствующего процентной доли скачанного файла

· getStatus

public int getStatus()

Получение текущего статуса загрузки

Возвращает:

статус загрузки

· pause

public void pause()

Метод приостановки загрузки

· resume

public void resume()

Метод возобновления загрузки

· cancel

public void cancel()

Метод отмены загрузки

· run

public void run()

Метод запуска потока загрузки, внутри него создается HTTP соединение с необходимыми параметрами и запускается скачивание

Определен для: run in interface java.lang. Runnable

Class DownloadManager

· java.lang. Object

· java.awt. Component

· java.awt. Container

· java.awt. Window

· java.awt. Frame

· javax.swing.JFrame

· org.agu.fizmat.pm.offlinebrowser. DownloadManager

· All Implemented Interfaces:

java.awt.image. ImageObserver, java.awt. MenuContainer, java.io. Serializable, java.util. Observer, javax.accessibility. Accessible, javax.swing. RootPaneContainer, javax.swing. WindowConstants

public class DownloadManager

extends javax.swing.JFrame

implements java.util. Observer

Класс – главное окно приложения

Модификатор и тип

Поле и описание

GlobalInfo

globalInfo

Переменная, хранящая общую информацию, необходимую для скачивания и обработки файлов

· Конструкторы

· DownloadManager

public DownloadManager()

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

· Методы

· update

public void update (java.util. Observable o, java.lang. Object arg)

Метод оповещения об изменении статуса загружаемых файлов

Определен для:

update in interface java.util. Observer

· main

public static void main (java.lang. String[] args)

Class DownloadsTableModel

· java.lang. Object

· javax.swing.table. AbstractTableModel

· org.agu.fizmat.pm.offlinebrowser. DownloadsTableModel

· All Implemented Interfaces:

java.io. Serializable, java.util. Observer, javax.swing.table. TableModel

public class DownloadsTableModel

extends javax.swing.table. AbstractTableModel

implements java.util. Observer

Класс реализует объект AbstractTableModel и предназначен для отображения информации о скачиваемых файлах.

· Конструкторы

· DownloadsTableModel

public DownloadsTableModel()

· Методы

· addDownload

public void add Download (Download download)

Метод добавления загрузки

Параметры:

download – поток загрузки файлов

· getDownload

public Download getDownload (int row)

Метод получения объекта Download по номеру строки в таблице

Параметры:

row – идентификатор строки в таблице

Возвращает:

Объект Download представляющий поток загрузки, информация о котором отображается на строке row

· clearDownload

public void clearDownload (int row)

Метод удаления загрузки для строки с номером row

Параметры:

row – номер строки

· getColumnCount

public int getColumnCount()

Метод получения числа столбцов в таблице

Определен для:

getColumnCount in interface javax.swing.table. TableModel

Возвращает:

число столбцов

· getColumnName

public java.lang. String getColumnName (int col)

Метод получения имени столбца по номеру

Определен для:

getColumnName in interface javax.swing.table. TableModel

Переопределение:

getColumnName in class javax.swing.table. AbstractTableModel

Параметры:

col – порядковый номер столбца в таблице

Возвращает:

имя столбца

· getColumnClass

public java.lang. Class getColumnClass (int col)

Метод получения класса по номеру столбца

Определен для:

getColumnClass in interface javax.swing.table. TableModel

Переопределение:

getColumnClass in class javax.swing.table. AbstractTableModel

Параметры:

col – номер столбца

Возвращает:

класс объекта, содержащегося в столбце с номером col

· getRowCount

public int getRowCount()

Метод получения количества строк в таблице

Определен для:

getRowCount in interface javax.swing.table. TableModel

Возвращает:

кол-во строк в таблице

· getValueAt

public java.lang. Object getValueAt (int row,

int col)

Метод получения содержимого ячейки таблицы на строке row и столбце col

Определен для:

getValueAt in interface javax.swing.table. TableModel

Параметры:

row – номер строки

col – номер столбца

Возвращает:

объект, содержащийся в ячейке таблицы

· update

public void update (java.util. Observable o,

java.lang. Object arg)

Метод, вызываемый при обновлении каких-либо данных в таблице

Определен для:

update in interface java.util. Observer

Параметры:

o – объект Observable

arg – объект который необходимо обновить

Class DownloadURL

· java.lang. Object

· org.agu.fizmat.pm.offlinebrowser. DownloadURL

· All Implemented Interfaces:

java.lang. Comparable<DownloadURL>

public class DownloadURL

extends java.lang. Object

implements java.lang. Comparable<DownloadURL>

Класс содержит необходимую информацию для обработки файлов

· Поля класса

Модификатор и тип

Название поля и описание

static int

COMPLETE

Статус, свидетельствующий том, что скачивание документа успешно завершено

static int

DOWNLOADING

Статус, свидетельствующий том, что документ в процессе скачивания

static int

ERROR

Статус, свидетельствующий том, что скачивание документа завершено с ошибкой

· Конструкторы

· DownloadURL

public DownloadURL (java.net.URL url,

int level,

java.lang. String tempFileName,

int status)

Конструктор класса

Параметры:

url – ссылка на файл

level – уровень вложенности документа

tempFileNmae – имя временного файла, в который сохраняется скачиваемый документ

status – статус обработки файла

· Методы

· toString

public java.lang. String toString()

Переопределение:

toString in class java.lang. Object

· equals

public boolean equals (java.lang. Object obj)

Метод проверки на равенство 2 объектов DownloadUrl. Сравниваются значения DownloadUrl.getUrl() каждого объекта

Переопределение:

equals in class java.lang. Object

Параметры:

obj – сравниваемый с текущим объект DownloadUrl

Возвращает:

· getUrl

public java.net.URL getUrl()

Метод получения ссылка на документ

Возвращает:

the url HTTP ссылка на документ

· setUrl

public void setUrl (java.net.URL url)

Метод устанавливает значение ссылки, указывающей на документ, который необходимо скачать

Параметры:

url – URL для сохранения

· getLevel

public int getLevel()

Метод получения уровня вложенности документа

Возвращает:

the level уровень вложенности

· setLevel

public void setLevel (int level)

Метод установки уровня вложенности документа

Параметры:

level – уровень вложенности

· getStatus

public int getStatus()

Получение статуса обработки документа, доступного по ссылке

Возвращает:

статус обработки документа, доступного по ссылке

· setStatus

public void setStatus (int status)

Метод установки текущего статуса обработки документа

· getTempFileName

public java.lang. Strin ggetTempFileName()

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

Возвращает:

имя файла

· setTempFileName

public void setTempFileName (java.lang. String tempFileName)

Метод установки значения имени временного файла, в который сохраняется загружаемый документ

Параметры:

имя – файла

· isNoDescendants

public boolean isNoDescendants()

Проверка, существуют ли дочерние документы, которые необходимо скачать

Возвращает:

boolean значение, true – есть дочерние элементы, false – нет

· setNoDescendants

public void setNoDescendants (boolean noDescendants)

Метод установки поля класса, указывающего есть ли у текущего дочерние документы

Параметры:

noDescendants – если true – дочерние элементы есть, если false – нет

· compareTo

public int compareTo (DownloadURL o)

Метод сравнения 2 объектов DownloadUrl. Сравниваются значения DownloadUrl.getUrl() каждого объекта

Определен для:

compareTo in interface java.lang. Comparable<DownloadURL>

Параметры:

o – сравниваемый с текущим объект DownloadUrl

Class GlobalInfo

· java.lang. Object

· org.agu.fizmat.pm.offlinebrowser. GlobalInfo

public class GlobalInfo

extends java.lang. Object

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

· Методы

· addPageInfo

public void addPageInfo (DownloadURL page)

Метод добавления новой страницы в глобальный список скачиваемых документов

Параметры:

page – объект DownloadURL, который будет загружен

· contains

public boolean contains (java.net.URL url)

Метод проверки, загружалась ли ранее эта страница.

Параметры:

url – URL страницы

Возвращает:

true – если страница уже загружалась, false если нет

· incompletePages

public int incompletePages()

Метод возвращает число необработанных еще страниц

Возвращает:

число страниц

· getGlobalUrlsList

public java.util. Set getGlobalUrlsList()

Метод получения Set из скачиваемых страниц

Возвращает:

Set скачиваемых страниц

· getInitialURL

public java.net.URL getInitialURL()

Метод получения начальной ссылки на страницу, с которой начинается скачивание

Возвращает:

the initialURL начальный URL

· getSiteSaveAbsolutePath

public java.lang. String getSiteSaveAbsolutePath()

Метод получения пути сохранения файлов

Возвращает:

путь сохранения файлов

· getSiteSaveTempPath

public java.lang. String getSiteSaveTempPath()

Метод получения пути для временного хранения файлов

Возвращает:

путь временного хранения файлов

· getAllPagesNumber

public int getAllPagesNumber()

Метод получения общего числа скачиваемых документов

Возвращает:

число всех скачиваемых файлов

· incrementPagesNumber

public void incrementPagesNumber()

Метод увеличения на 1 количества всех ссылок

· getCompletedPagesNumber

public int getCompletedPagesNumber()

Метод получения числа обработанных документов

Возвращает:

число обработанных документов

· incrementCompletedPagesNumber

public void incrementCompletedPagesNumber()

Метод увеличивает на 1 число обработанных документов

· getErrorPagesNumber

public int getErrorPagesNumber()

Метод возвращает число страниц, обработка которых завершилась с ошибкой

Возвращает:

число страниц обработанных с ошибкой

· incrementErrorPagesNumber

public void incrementErrorPagesNumber()

Метод увеличивает на 1 число страниц, обработка которых завершилась с ошибкой

· createSiteStructure

public void createSiteStructure()

Метод перемещает и переименовывает файлы из места временного хранения и создает нужную структуру каталогов

Class Parser

· java.lang. Object

· org.agu.fizmat.pm.offlinebrowser.parser. Parser

public class Parser

extends java.lang. Object

Класс, содержит вспомогательные методы для обработки документов и обновления ссылок в них

· Конструктор

· Parser

publicParser()

· Методы

· isParseable

public static boolean isParseable (java.lang. String contentType)

Метод проверяет по свойству Content-type скачиваемого документа необходимо ли выполнять разбор документа для обновления в нем ссылок

Параметры:

contentType – строка содержащая Content-type документа

Возвращает:

если true, то необходим разбор документа, если false то разбор не требуется

· makeURL

public java.net.URL makeURL (java.lang. String link,

java.net.URL page)

Метод создания объекта URL из ссылок различного вида найденных в документе

Параметры:

link – строковое представление ссылки в документе

page – URL текущей страницы

Возвращает:

URL ссылки представленной в параметре link

· parseCSSDocument

public java.util. List<DownloadURL> parseCSSDocument (DownloadUR Lpage,

java.lang. String sourceFileName,

java.lang. String destFileName)

Метод разбора CSS документа и обновления в нем ссылок на загруженные ресурсы. Замена ссылок происходит применением регулярных выражений к аттрибутам типа url(link)

Параметры:

page – текущая страница

sourceFileName – имя исходного файла

destFileName – имя файла с уже преобразованными ссылками

Возвращает:

список объектов DownloadURL, которые представляют собой ссылки на дочерние страницы

· parseLinksInDocument

public java.util. List<DownloadURL> parseLinksInDocument (DownloadManager dm,

DownloadUR Lpage,

java.lang. String sourceFileName,

java.lang. String destFileName,

java.lang. String charsetName)

Метод разбора исходного HTML документа. Считывает исходный файл, загруженный по ссылке page и заменяет ссылки найденные в base[href], a[href], img[src], link[href], script[src] на ссылке на загружаемые файлы. Для обработки используется библиотеку Jsoup

Параметры:

dm – объект DownloadManager, необходим для получения доступа к глобальному списку ссылок

page – ссылка на текущую страницу

sourceFileName – имя исходного файла

destFileName – имя файла, в котором исходные ссылки уже заменены на локальные

charsetName – кодировка исходного файла

Возвращает:

список ссылок найденных в файле

Class ProgressRenderer

· java.lang. Object

· java.awt. Component

· java.awt. Container

· javax.swing.JComponent

· javax.swing.JProgressBar

· org.agu.fizmat.pm.offlinebrowser. ProgressRenderer

· All Implemented Interfaces:

java.awt.image. ImageObserver, java.awt. MenuContainer, java.io. Serializable, javax.accessibility. Accessible, javax.swing. SwingConstants, javax.swing.table. TableCellRenderer

public class ProgressRenderer

extends javax.swing.JProgressBar

implements javax.swing.table. TableCellRenderer

Класс расширяет JProgressBar для отображения статус загрузки

· Конструкторы

· ProgressRenderer

public ProgressRenderer (int min, int max)

Конструктор класса

· Методы

· getTableCellRendererComponent

public java.awt. Component getTableCellRendererComponent (javax.swing.JTable table,

java.lang. Object value,

boolean isSelected,

boolean hasFocus,

int row,

int column)

Метод возвращает JProgressBar для ячейки таблицы (row, column)

Определен для:

getTableCellRendererComponent in interface javax.swing.table. TableCellRenderer

Параметры:

table – таблица отображающая статус загрузок

value – значение

isSelected – выбрано

hasFocus – активно

row – номер строки

column – номер столбца

Возвращает:

JProgressBar со статусом загрузки

Заключение

В рамках данной дипломной работы мы постарались создать приложение, которое может быть использовано для сохранения данных с Интернет страниц. Было разработано приложение, достоинствами которого является:

1. Возможность дозагрузки не полностью загруженных файлов.

2. Обработка файлов различных типов.

3. Поддержка многопоточной обработки.

4. Кроссплатформенность.

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

Помимо вышеперечисленного, приложение спроектировано таким образом, что пользователь может изменять программу в соответствии со своими требованиями.

Литература

1. Герберт Шилдт, Джеймс Холмс – Искусство программирования на JAVA. Москва: издательский дом «Вильямс». 2005 г., 336 стр.

2. Брюсс Эккель – Философия Java. Библиотека программиста. 4-е издание. Санкт-Петербург. 2009 г., 640 стр.

3. Учебник по HTML: http://ru.html.net/tutorials/html/

4. Герберт Шилдт – Полный справочник по JAVA. Под редакцией Т.Н. Артеменко, В.Г. Павлютин. 7-е издание – Москва: Издательский дом «Вильямс», 2007 г., 1024 стр.

5. Jonathan Hedley – «Jsoup: Java HTML Parser». http://jsoup.org/

6. Майкл Эферган – Java: справочник. Издательство «Питер Ком», 1998 г.

7. Кен Арнольд, Джеймс Гослинг – Язык программирования Java. Издательство «Питер-Пресс», 1997 г.

8. Патрик Нотон, Герберт Шилдт – Полный справочник по Java. Издательство «Диалектика», 1997 г.

Поделиться работой
Поделиться в telegram
Поделиться в whatsapp
Поделиться в vk
Поделиться в facebook
Поделиться в twitter
Леонид Федотов
Леонид Федотов
Окончил НИУ ВШЭ факультет компьютерных наук. Сам являюсь кандидатом наук. По специальности работаю 13 лет, за это время создал 8 научных статей и 2 диссертации. В компании подрабатываю в свободное от работы время уже более 5 лет. Нравится помогать школьникам и студентам в решении контрольных работ и написании курсовых проектов. Люблю свою профессию за то, что это направление с каждым годом становится все более востребованным и актуальным.

Статьи по дипломным