Без каких-либо сторонних библиотек минимальный клиент для загрузки файлов HTTP полностью реализован на Java Socket. Полная демонстрация того, как реализовать заголовок HTTP -запроса для загрузки файлов через сокет для отправки пакета HTTP ответа (заголовок ответа, корпуса ответа) из сокета и Parse и сохранения содержимого файла. Как реализовать пользовательский интерфейс через Swingwork, чтобы отобразить прогресс загрузки в режиме реального времени.
Сначала посмотрите на часть пользовательского интерфейса:
【Добавить загрузку】 кнопка:
Нажмите на всплывающее окно ввода URL. После того, как пользователь хочет загрузить URL -адрес файла в поле ввода, нажмите кнопку [OK], чтобы запустить.
скачать
【Очистите полную кнопку:
Очистить все загруженные списки файлов
Статус загрузки файла разделен на следующие типы:
пакет com.gloomyfish.socket.tutorial.http.download; public enum downlystatus {not_started, in_process, завершен, ошибка} Часть пользовательского интерфейса в основном выполняется с использованием компонентов качания. Нажмите [Добавить загрузку], чтобы выполнить код следующим образом:
final JDialog Dialog = new jDialog (это, "добавить ссылку на файл", true); dialog.getContentPane (). SetLayout (new BorderLayout ()); // dialog.setsize (новое измерение (400 200)); окончательная панель urlfilepanel = new urlfilepanel (); panel.setUplistener (new ActionListener () {@Override public void actionPerformed (actionEvent e) {if ("ok" .equals (e.getActionCommand ())) {if (panel.validateInput ()) {downloadDetailStatusInfomodel Data = new DownetAtleSINFOMODEL (DETALIDID TableModel.getData (). (Data); dialog.getContentPane (). Add (панель, borderlayout.center); dialog.pack (); Центр (диалог); dialog.setvisible (true); Код, выполненный кнопкой [Clear Complete], выглядит следующим образом:
private void cleardownload () {list <dightDetailStatusInfomodel> downloadedlist = new ArrayList <dightDetailStatusInfomodel> (); для (downloaddetailStatusInfomodel fileStatus: tableModel.getData ()) {if (fileStatus.getStatus (). ToString (). equals (downloadStatus.completed.toString ())) {downloadList.Add (fileStatus); }} tablemodel.getData (). Removeall (DownloadedList); rebreshui (); } Код для центрирования компонента jframe заключается в следующем:
Public Static Void Center (окно w) {Dimension us = w.getSize (); Размер их = toolkit.getDefaulttoolkit (). GetScreensize (); int newx = (the.width - us.width) / 2; int newy = (this.height - us.height) / 2; W.SetLocation (Newx, Newy); }Часть реализации протокола HTTP:
Обзор: Основная структура и объяснение заголовка HTTP -запроса и соответствующие пакеты заголовков
HTTP -запрос: стандартный HTTP -пакет запросов, такой как
Там может быть несколько заголовков запроса, и тело сообщений не может быть, что не требуется. Формат линии запроса заключается в следующем:
Request-line = method sp request-uri sphttp-version crlf приводит пример следующим образом:
Request-line = get http://www.w3.org/pub/www/theproject.htmlhttp/1.1/r/n
где SP представляет пробелы, CRLF представляет разрывы обратной линии кареты/R/N
Если вы хотите загрузить файл, используйте Post, чтобы заполнить данные в тело сообщения. Отправить один
Простое сообщение HTTP -запроса выглядит следующим образом:
Ответ HTTP: стандартное ответное сообщение HTTP заключается в следующем
Первое, что вы получите, - это линия статуса, ее формат заключается в следующем:
Статус-line = http-version sp status-codesp dase-phrase crlf, простой пример строки статуса заключается в следующем: Status-line = http/1.1 200 OK, как правило, любимый код статуса, который даст вам много подсказок, наиболее распространенными являются коды статуса, такие как 404, 500 и т. Д. Самая важная вещь для загрузки файла-это проверить длину содержимого и тип контента в заголовке ответа HTTP.
Длина и тип файла объявляются отдельно. Другие, такие как приемные диапазоны, представляют, сколько байтов принимается. Возможно, используется в многопоточных загрузках. После понимания формата пакета HTTP -запроса и ответа мы можем проанализировать контент в формате пакета через сокет, отправлять и прочитать HTTP -запрос и ответ. Конкретные шаги
следующее:
1. Установите соединение сокета на основе URL -адреса файла, введенного пользователем
Url url = new URL (fileInfo.getFileurl ()); String host = url.gethost (); int port = (url.getport () == -1)? url.getdefaultport (): url.getport (); System.out.println ("host name =" + host); System.out.println ("port =" + port); System.out.println ("file uri =" + url.getFile ()); // Создать сокет и начать построить сокет строки запроса = new Socket (); Outdaddress address = new InetsocketAddress (хост, порт); ocket.connect (адрес); Класс URL используется для превращения строки URL, введенной пользователем в URL -адрес, который проще разобрать.
2. Стройте HTTP -запросы
BufferedWriter BufferedWriter = New BufferedWriter (новый outputStreamWriter (socket.getOutputStream (), "utf8")); String requestStr = "get" + url.getFile () + "http/1.1/r/n"; // Строка запроса // Создание заголовка запроса - построить заголовок HTTP -запроса (заголовок запроса) string hostheader = "host:" + host + "/r/n"; String rackTheader = "Принять: text/html, application/xhtml+xml, application/xml; q = 0,9,*/*; q = 0,8/r/n"; String charsetheader = "accept-charset: gbk, utf-8; q = 0,7,*; q = 0,3/r/n"; String languageHeader = "accept-language: zh-cn, zh; q = 0,8/r/n"; String keepHeader = "connection: close/r/n";
3. Отправить HTTP -запрос
// Отправить http -запрос BufferedWriter.write (requestStr); BufferedWriter.Write (Hostheader); BufferedWriter.Write (AccomingTheader); BufferedWriter.Write (Charsetheader); BufferedWriter.Write (LanguageHeader); BufferedWriter.Write (KeepHeader); BufferedWriter.Write ("/r/n"); // Сообщение заголовка запроса Отправка конечного флага BufferedWriter.flush (); 4. Примите ответ http и контент parse, а также напишите в созданный файл
// Подготовка к приему заголовки ответов http и Parse CustomDataInputStream input = new CustomDataInputStream (socket.getInputStream ()); File myfile = new File (fileInfo.getStoreLocation () + file.separator + fileInfo.getFilename ()); Строка содержимого = null; HttpresponseHeaderParser responseHeader = new httpresponseHeaderParser (); BufferedOutputStream output = new BufferedOutputStream (New FileOutputStream (myFile)); Boolean hasdata = false; while ((content = input.readhttpresponsehaderline ())! = null) {System.out.println ("Контакт заголовка ответа ->>" + content); chessceptHeader.AdresponseHeaderLine (Content); if (content.length () == 0) {hasdata = true; } if (hasdata) {int totalbytes = responseHeader.getFileLength (); if (totalbytes == 0) разрыв; // Нет тела ответа и данные int offset = 0; байт [] mydata = null; if (totalBytes> = 2048) {myData = новый байт [2048]; } else {myData = new Byte [totalBytes]; } int numOfbytes = 0; while ((numofbytes = input.read (mydata, 0, mydata.length))> 0 && offset <totalbytes) {offset += numofbytes; float p = ((float) смещение) / ((float) totalbytes) * 100,0f; if (offset> totalbytes) {numofbytes = numofbytes + totalbytes - offset; p = 100,0F; } output.write (mydata, 0, numofbytes); UpdateStatus (P); } hasdata = false; перерыв; }} Простой класс заголовка HTTP -ответа HttpresponseHeadErparser выглядит следующим образом:
пакет com.gloomyfish.socket.tutorial.http.download; импортировать java.util.hashmap; импортировать java.util.map; /** * Это может анализировать заголовок объекта, голова ответа * и строка ответа <код состояния, charset, ect ...> * см. RFC2616. Для заголовков ответов HTTP см. В документе RFC, который подробно описан! ! */ public class httpresponseHeaderParser {public final Static String content_length = "Content-kength"; public final Static String content_type = "content-type"; публичная окончательная статическая строка accept_ranges = "accetp-ranges"; Приватная карта <строка, строка> headermap; public httpresponseHeaderParser () {HeaderMap = new HashMap <string, string> (); }/** * <p> Получить пару значения ключа заголовка ответа </p> * @param responseHeaderLine */public void addResponseHeaderLine (string chesspecterline) {if (repplyHeaderLine.contains (":")) {string [] keyvalue = repplionHeaderLine.split (":"); if (keyvalue [0] .EqualsIgnoreCase (content_length)) {headermap.put (content_length, keyvalue [1]); } else if (keyvalue [0] .EqualSignoreCase (content_type)) {headermap.put (content_type, keyvalue [1]); } else {headermap.put (keyvalue [0], keyvalue [1]); }}} public int getFileLength () {if (headermap.get (content_length) == null) {return 0; } return integer.parseint (headermap.get (content_length)); } public String getFileType () {return headermap.get (content_type); } public map <string, string> getAllheaders () {return headermap; }}Выше приведено все об этой статье, я надеюсь, что для всех будет полезно изучать программирование Java.