Sem nenhuma biblioteca de terceiros, um cliente mínimo de download de arquivo http é implementado inteiramente com base no soquete Java. Uma demonstração completa de como implementar o cabeçalho da solicitação HTTP para baixar arquivos através do soquete para enviar um pacote de resposta HTTP (cabeçalho de resposta, corpo de resposta) do soquete e analisar e salvar o conteúdo do arquivo. Como realizar a atualização da UI através do swingwork para exibir o progresso do download em tempo real.
Primeiro olhe para a parte da interface do usuário:
【Adicionar download】 Botão:
Clique na caixa de entrada do URL pop-up. Depois que o usuário quiser baixar o URL do arquivo na caixa de entrada, clique no botão [OK] para iniciar.
download
【Limpar o botão completo】:
Lista de arquivos baixada limpa todos os arquivos
O status de download do arquivo é dividido nos seguintes tipos:
pacote com.gloomyfish.socket.tutorial.http.download; public enum downloadstatus {não_started, in_process, concluído, erro} A parte da interface do usuário é feita principalmente usando componentes de swing. Clique em [Adicionar download] para executar o código da seguinte forma:
diálogo final jdialog = novo jdialog (this, "Adicionar link de arquivo", true); dialog.getContentPane (). Setlayout (new BorderLayout ()); // dialog.setsize (nova dimensão (400.200)); Painel final de urlfilepanel = new UrlFilePanel (); panel.setUpListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { if("OK".equals(e.getActionCommand())){ if(panel.validateInput()) { DownloadDetailStatusInfoModel data = new DownloadDetailStatusInfoModel(panel.getValidFileURL()); Tablemodel.getData () Add (Data); dialog.getContentPane (). add (painel, borderlayout.center); dialog.pack (); centro (diálogo); dialog.setVisible (true); O código executado pelo botão [Clear completo] é o seguinte:
private void clearDownloaded () {list <downloadDetailStatusInFomodel> DownloadList = new ArrayList <OrlownDetailStatusInFomodel> (); para (DownloadDetailStatusInFomodel FileStatus: Tablemodel.getData ()) {if (FileStatus.getStatus (). Tostring (). Equals (downloadstatus.completed.tostring ())) {downloadlist.add (filestatus); }} Tablemodel.getData (). Removeall (DownloadList); refreshui (); } O código para centralizar o componente JFrame é o seguinte:
public static void Center (janela w) {dimension US = w.getSize (); Dimensão eles = ferramentakit.getDefaultToolkit (). GetScreensize (); int newx = (eles.Width - US.Width) / 2; int newy = (eles.Height - US.Height) / 2; W.SetLocation (Newx, Newy); }Parte da implementação do protocolo HTTP:
Visão geral: estrutura básica e explicação do cabeçalho da solicitação HTTP e pacotes de cabeçalho correspondentes
Solicitação HTTP: um pacote de solicitação HTTP padrão, como
Pode haver vários cabeçalhos de solicitação, e o corpo da mensagem pode ser nenhum, o que não é necessário. O formato da linha de solicitação é o seguinte:
Solicitação-linha = método sp request-uri sphttp-version crlf dá um exemplo da seguinte forma:
Request-line = obtenha http://www.w3.org/pub/www/theproject.htmlhttp/1.1/r/n
Onde o SP representa espaços, o CRLF representa quebras de linha de retorno do carro/r/n
Quando você deseja fazer upload de um arquivo, use a postagem para preencher os dados no corpo da mensagem. Envie um
Uma mensagem de solicitação HTTP simples é a seguinte:
Resposta HTTP: Uma mensagem de resposta HTTP padrão é a seguinte
A primeira coisa que você recebe é a linha de status, seu formato é o seguinte:
STATUS-LINE = HTTP-VERSIONS SP STATUS-CODESP RAIL-FRASE CRLF, um exemplo simples de uma linha de status é o seguinte: status-line = http/1.1 200 OK Geralmente, o favorito de todos é o código de status que fornecerá a você muitos sotts, que os códigos mais comuns são referidos para o status, como 404, 500, etc. O significado do código de status. A coisa mais importante para baixar um arquivo é verificar o comprimento de conteúdo e o tipo de conteúdo no cabeçalho da resposta HTTP.
O comprimento e o tipo de arquivo são declarados separadamente. Outros, como faixas de aceitação, representam quantos para quantos bytes são aceitos. Possivelmente usado em downloads com vários threads. Depois de entender o formato do pacote de solicitação e resposta HTTP, podemos analisar o conteúdo no formato do pacote através do soquete, enviar e ler a solicitação e resposta HTTP. Etapas específicas
do seguinte modo:
1. Estabeleça uma conexão de soquete com base no URL do arquivo inserido pelo usuário
Url url = novo url (fileInfo.getfileurl ()); String host = url.gethost (); int porta = (url.getport () == -1)? url.getDefaultPort (): url.getport (); System.out.println ("Nome do host =" + host); System.out.println ("port =" + porta); System.out.println ("arquivo uri =" + url.getfile ()); // Crie soquete e comece a construir o soquete da linha de solicitação = new Socket (); Endereço do SocketAddress = novo INetSocketAddress (host, porta); Socket.Connect (endereço); A classe URL é usada para transformar a sequência URL inserida pelo usuário em um URL que é mais fácil de analisar.
2. Construa solicitações HTTP
Bufferwriter bufferwriter = new bufferwriter (new outputStreamWriter (Socket.getOutputStream (), "utf8")); String requeststr = "get" + url.getfile () + "http/1.1/r/n"; // Linha de solicitação // Construa o cabeçalho da solicitação - Construa o cabeçalho da solicitação HTTP (cabeçalho da solicitação) string hosttheader = "host:" + host + "/r/n"; String accepTheader = "Aceitar: texto/html, aplicação/xhtml+xml, aplicação/xml; q = 0,9,*/*; q = 0,8/r/n"; String charsetheader = "aceitar-caractere: gbk, utf-8; q = 0,7,*; q = 0,3/r/n"; String LanguageHeader = "Aceitar-Language: ZH-CN, ZH; Q = 0,8/R/N"; String upnetherser = "conexão: fechar/r/n";
3. Envie a solicitação HTTP
// Envie o http request bufferwriter.write (requeststr); bufferwriter.write (hósteade); BufferWriter.Write (AcepTheader); bufferwriter.write (charsetheader); bufferwriter.write (idioma); bufferwriter.write (upheader); bufferwriter.write ("/r/n"); // Solicite a mensagem do cabeçalho enviando o sinalizador final bufferwriter.flush (); 4. Aceite a resposta HTTP e o conteúdo da análise e escreva no arquivo criado
// Prepare -se para aceitar cabeçalhos de resposta HTTP e analisar o CustomDatainputStream input = new CustomDatainputStream (Socket.getInputStream ()); Arquivo myfile = novo arquivo (fileInfo.getStorelocation () + file.separator + fileInfo.getFilename ()); String content = null; HttpResponseHeaderParSer Responser = New HttpResponseHeaderParser (); BufferoudOutputStream Output = new BufferoudOutputStream (new FileOutputStream (MyFile)); boolean hasdata = false; while ((content = input.readhttpResponseHeaderline ())! = null) {System.out.println ("Contato do cabeçalho da resposta ->>" + content); ResponseHeader.addresponseHeaderline (content); if (content.Length () == 0) {hasdata = true; } if (hasData) {int totalbytes = ResponseHeader.getFileLength (); if (totalbytes == 0) quebra; // sem corpo de resposta e dados int offset = 0; byte [] mydata = null; if (totalbytes> = 2048) {myData = novo byte [2048]; } else {mydata = novo byte [totalbytes]; } int numefbytes = 0; while ((numefbytes = input.read (mydata, 0, mydata.length))> 0 && deslocamento <totalbytes) {offset += numefbytes; flutuador p = ((float) deslocamento) / ((float) totalbytes) * 100.0f; if (deslocamento> totalbytes) {numefbytes = numefbytes + totalbytes - deslocamento; p = 100,0f; } output.write (mydata, 0, numefbytes); UpdateStatus (P); } hasdata = false; quebrar; }} A classe de cabeçalho de resposta HTTP simples HTTPRESPONSEHEADERPARSER Código é a seguinte:
pacote com.gloomyfish.socket.tutorial.http.download; importar java.util.hashmap; importar java.util.map; /** * Pode analisar o cabeçalho da entidade, a cabeça de resposta * e a linha de resposta <código de status, charset, ect ...> * Consulte RFC2616. Para cabeçalhos de resposta HTTP, consulte o documento RFC, que é descrito em detalhes! ! */ classe pública httproponseHeaderParser {public final static string content_length = "content-length"; public final static string content_type = "content-type"; Public final Static String aceit_anges = "Accetp-Ranges"; mapa privado <string, string> headermap; public HTTPRESPOnseHeaderParser () {headerMap = new Hashmap <String, String> (); }/** * <p> Obtenha o par de valores da chave do cabeçalho da resposta </p> * @param ResponseHeaderLine */public void addResponseHeaderline (String ResponserHeaderline) {if (ResponserLeaderline.Contains (":")) {String [] keyValue = ResponserLine.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); } mapa público <string, string> getAllHeaders () {return headerMap; }}O exposto acima é tudo sobre este artigo, espero que seja útil para todos aprenderem a programação Java.