Sin ninguna biblioteca de terceros, un cliente de descarga de archivos HTTP mínimo se implementa completamente basado en Java Socket. Una demostración completa de cómo implementar el encabezado de solicitud HTTP para descargar archivos a través de Socket para enviar un paquete de respuesta HTTP (encabezado de respuesta, cuerpo de respuesta) desde el socket y analizar y guardar el contenido del archivo. Cómo realizar la actualización de la interfaz de usuario a través de Swingwork para mostrar el progreso de descarga en tiempo real.
Primero mira a la parte de la interfaz de usuario:
【Agregue el botón Descargar】:
Haga clic en el cuadro de entrada URL emergente. Después de que el usuario desea descargar la URL del archivo al cuadro de entrada, haga clic en el botón [Aceptar] para iniciar.
descargar
【Clare el botón Complete】:
Borrar todas las listas de archivos descargados
El estado de descarga de archivos se divide en los siguientes tipos:
paquete com.gloomyfish.socket.tutorial.http.download; Public Enum downloadStatus {Not_started, in_process, completado, error} La parte de la interfaz de usuario se realiza principalmente usando componentes de swing. Haga clic en [Agregar descarga] para ejecutar el código de la siguiente manera:
diálogo final JDialog = new JDialog (this, "Agregar enlace de archivo", true); dialog.getContentPane (). SetLayout (new BorderLayout ()); // diálogo.setsize (nueva dimensión (400,200)); panel final de urlfilepanel = new UrlFilePanel (); panel.setUplistener (new ActionListener () {@Override public Void ActionPerformed (ActionEvent E) {if ("OK" .Equals (E.GetActionCommand ()) {if (panel.validateInput ()) {downloadDetailSinfomodel data = new DownloadDatusInfomodel (Panel.getValidfileUtfileUtfileUsl (); Tablemodel.getData (). Add (Data); dialog.getContentPane (). add (panel, borderLayout.center); dialog.pack (); centro (diálogo); dialog.setVisible (verdadero); El código ejecutado por el botón [Clear Complete] es el siguiente:
Private void Cleardownloaded () {List <DownloadDetailStatusInfomodel> downloadedList = new ArrayList <downloadDetailStatUsInfomodel> (); para (downloadDetailStatusInfomodel filestatus: TableModel.getData ()) {if (fileStatus.getStatus (). ToString (). Equals (downloadStatus.completed.ToString ()) {downloadedList.Add (fileStatus); }} TableModel.getData (). RemoveAll (DownloadedList); refreshui (); } El código para centrar el componente jframe es el siguiente:
Centro vacío estático público (ventana w) {dimension us = w.getSize (); Dimension the = toolkit.getDefaultToolkit (). GetsCreensize (); int newx = (thes.width - us.width) / 2; int newy = (ellos. W.SetLocation (Newx, Newy); }Parte de implementación del protocolo HTTP:
Descripción general: Estructura básica y explicación del encabezado de solicitud HTTP y los paquetes de encabezado correspondientes
Solicitud HTTP: un paquete de solicitud HTTP estándar como
Puede haber múltiples encabezados de solicitud, y el cuerpo de mensajes no puede ser ninguno, lo cual no es necesario. El formato de la línea de solicitud es el siguiente:
Request-line = método sp request-uri sphttp-version crlf da un ejemplo de lo siguiente:
Request-line = Get http://www.w3.org/pub/www/theproject.htmlhttp/1.1/r/n
Donde SP representa espacios, CRLF representa descansos de la línea de retorno del carro/R/N
Cuando desee cargar un archivo, use la publicación para completar los datos en el cuerpo de mensajes. Enviar uno
Un simple mensaje de solicitud HTTP es el siguiente:
Respuesta HTTP: un mensaje de respuesta HTTP estándar es el siguiente
Lo primero que obtienes es la línea de estado, su formato es el siguiente:
Status-line = http-version sp status-codes-frase-frase CRLF, un ejemplo simple de una línea de estado es el siguiente: status-line = http/1.1 200 ok en general, el favorito de todos los favoritos es el código de estado que le dará muchas indicaciones, los más comunes son códigos de estado como 404, 500, etc. El significado del código de estado se puede referir a la explicación en RFC2616. Lo más importante para descargar un archivo es verificar el contenido y el tipo de contenido en el encabezado de respuesta HTTP.
La longitud y el tipo de archivo se declaran por separado. Otros, como los rangos de aceptación, representan cuántos se aceptan cuántos bytes. Posiblemente utilizado en descargas de múltiples subprocesos. Después de comprender el formato de paquete de la solicitud y la respuesta HTTP, podemos analizar el contenido en el formato de paquete a través de Socket, enviar y leer la solicitud y respuesta HTTP. Pasos específicos
como sigue:
1. Establezca una conexión de socket basada en la URL de archivo ingresada por el usuario
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 ("puerto =" + puerto); System.out.println ("file uri =" + url.getFile ()); // Crear socket y comenzar a construir el socket de línea de solicitud de solicitud = new Socket (); Dirección de socketaddress = nueva inetSocketAddress (host, puerto); socket.connect (dirección); La clase URL se usa para convertir la cadena de URL ingresada por el usuario en una URL que es más fácil de analizar.
2. Construir solicitudes HTTP
BufferedWriter BufferedWriter = new BufferedWriter (nuevo OutputStreamWriter (Socket.getOutputStream (), "UTF8")); String requestStr = "get" + url.getFile () + "http/1.1/r/n"; // Línea de solicitud // Construye el encabezado de solicitud: construya el encabezado de solicitud HTTP (encabezado de solicitud) cadena hostheader = "host:" + host + "/r/n"; String acceptheader = "Acept: Text/Html, Application/XHTML+XML, Aplicación/XML; Q = 0.9,*/*; Q = 0.8/r/n"; String charsetheader = "Acept-Charset: GBK, UTF-8; Q = 0.7,*; q = 0.3/r/n"; String LanguageHeader = "Aceptar-Language: ZH-CN, ZH; Q = 0.8/R/N"; String KeepHeader = "Conexión: Close/R/N";
3. Enviar solicitud HTTP
// Enviar solicitud http bufferedwriter.write (requeststr); BufferedWriter.Write (Hostheader); BufferedWriter.Write (AccepTheader); BufferedWriter.Write (Charsetheader); BufferedWriter.Write (LanguageHeader); bufferedwriter.write (Keepheader); bufferedwriter.write ("/r/n"); // Solicitar mensaje de encabezado enviando FIND BACKERDWRITER.FLUSH (); 4. Acepte la respuesta HTTP y el contenido de análisis, y escriba en el archivo creado
// Prepárese para aceptar encabezados de respuesta HTTP y analizar customDatainputStream Entry = new CustomDatainPutStream (Socket.GetInputStream ()); Archivo myFile = nuevo archivo (fileInfo.getSteReLocation () + file.separator + fileInfo.getFileName ()); String content = null; HttpResponseHeaderParser ResponseHeader = new HttPResponseHeaderParser (); BufferedOutputStream output = new BufferedOutputStream (nuevo FileOutputStream (myFile)); Boolean HasData = false; while ((content = input.readHttPResponseHeaderLine ())! = NULL) {System.out.println ("Contacto de encabezado de respuesta ->>" + contenido); ResponseHeader.AddResponseHeaderLine (contenido); if (content.length () == 0) {HasData = true; } if (HasData) {int TotalBytes = ResponseHeader.getFilelength (); if (totalbytes == 0) ruptura; // Sin cuerpo de respuesta y datos int offset = 0; byte [] myData = null; if (totalBytes> = 2048) {myData = new Byte [2048]; } else {myData = new Byte [TotalBytes]; } int numOfBytes = 0; while ((numOfBytes = input.read (myData, 0, myData.length))> 0 && offset <totalBytes) {offset += numOfBytes; flotante p = (((float) offset) / (((float) Totalbytes) * 100.0f; if (offset> totalbytes) {numOfBytes = numOfBytes + totalBytes - offset; p = 100.0f; } output.write (myData, 0, numOfBytes); UpdateStatus (P); } HasData = falso; romper; }} El simple código de análisis del encabezado de respuesta HTTP de HTTP
paquete com.gloomyfish.socket.tutorial.http.download; import java.util.hashmap; import java.util.map; /** * Puede analizar el encabezado de la entidad, el cabezal de respuesta * y la línea de respuesta <código de estado, Charset, ECT ...> * Consulte RFC2616. Para los encabezados de respuesta HTTP, consulte el documento RFC, ¡que se describe en detalle! ! */ public class httPResponseHeaderParser {public final static string content_length = "content-length"; Public final static string content_type = "content-type"; Public final static string acept_ranges = "Accetp-Ranges"; mapa privado <string, string> headermap; public HttPResponseHeaderParser () {headermap = new HashMap <String, String> (); }/** * <p> Obtenga el par de valor de clave de encabezado de respuesta </p> * @param ResponseHeaderLine */public void addResponseHeaderline (String ResponseHeaderLine) {if (ResponseHeaderLine.Contains (":")) {String [] keyValue = ResponseHeaderLine.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; }}Lo anterior se trata de este artículo, espero que sea útil para todos aprender la programación de Java.