文章分类

站点统计

  • 分类总数: 13 个
  • 文章总数: 145 篇
  • 评论总数: 35 条
  • 附件总数: 59 个
  • 建站日期: 2008-08-18
  • 访问总数: 387352 人次
  • RSS订阅: 文章|评论

NanoHTTPD version 1.11

Admin 于 2008-10-04 09:40:10 发表Java

订阅: http://www.kaiyuan8.org/Feed/Article_107.aspx
引用: 点这里获取地址 (UTF-8)
Lucene.Net基本用法 < NanoHTTPD version 1.11 > NanoHTTPD example

  1. import java.io.*; 
  2. import java.util.*; 
  3. import java.net.*; 
  4.  
  5. /** 
  6.  * A simple, tiny, nicely embeddable HTTP 1.0 server in Java 
  7.  * 
  8.  * <p> NanoHTTPD version 1.11, 
  9.  * Copyright &copy; 2001,2005-2008 Jarno Elonen (elonen@iki.fi, http://iki.fi/elonen/) 
  10.  * 
  11.  * <p><b>Features + limitations: </b><ul> 
  12.  * 
  13.  *    <li> Only one Java file </li> 
  14.  *    <li> Java 1.1 compatible </li> 
  15.  *    <li> Released as open source, Modified BSD licence </li> 
  16.  *    <li> No fixed config files, logging, authorization etc. (Implement yourself if you need them.) </li> 
  17.  *    <li> Supports parameter parsing of GET and POST methods </li> 
  18.  *    <li> Supports both dynamic content and file serving </li> 
  19.  *    <li> Never caches anything </li> 
  20.  *    <li> Doesn't limit bandwidth, request time or simultaneous connections </li> 
  21.  *    <li> Default code serves files and shows all HTTP parameters and headers</li> 
  22.  *    <li> File server supports directory listing, index.html and index.htm </li> 
  23.  *    <li> File server does the 301 redirection trick for directories without '/'</li> 
  24.  *    <li> File server supports simple skipping for files (continue download) </li> 
  25.  *    <li> File server uses current directory as a web root </li> 
  26.  *    <li> File server serves also very long files without memory overhead </li> 
  27.  *    <li> Contains a built-in list of most common mime types </li> 
  28.  *    <li> All header names are converted lowercase so they don't vary between browsers/clients </li> 
  29.  * 
  30.  * </ul> 
  31.  * 
  32.  * <p><b>Ways to use: </b><ul> 
  33.  * 
  34.  *    <li> Run as a standalone app, serves files from current directory and shows requests</li> 
  35.  *    <li> Subclass serve() and embed to your own program </li> 
  36.  *    <li> Call serveFile() from serve() with your own base directory </li> 
  37.  * 
  38.  * </ul> 
  39.  * 
  40.  * See the end of the source file for distribution license 
  41.  * (Modified BSD licence) 
  42.  */ 
  43. public class NanoHTTPD 
  44.     // ================================================== 
  45.     // API parts 
  46.     // ================================================== 
  47.  
  48.     /** 
  49.      * Override this to customize the server.<p> 
  50.      * 
  51.      * (By default, this delegates to serveFile() and allows directory listing.) 
  52.      * 
  53.      * @parm uri    Percent-decoded URI without parameters, for example "/index.cgi" 
  54.      * @parm method "GET", "POST" etc. 
  55.      * @parm parms  Parsed, percent decoded parameters from URI and, in case of POST, data. 
  56.      * @parm header Header entries, percent decoded 
  57.      * @return HTTP response, see class Response for details 
  58.      */ 
  59.     public Response serve( String uri, String method, Properties header, Properties parms ) 
  60.     { 
  61.         System.out.println( method + " '" + uri + "' " ); 
  62.  
  63.         Enumeration e = header.propertyNames(); 
  64.         while ( e.hasMoreElements()) 
  65.         { 
  66.             String value = (String)e.nextElement(); 
  67.             System.out.println( "  HDR: '" + value + "' = '" + 
  68.                                 header.getProperty( value ) + "'" ); 
  69.         } 
  70.         e = parms.propertyNames(); 
  71.         while ( e.hasMoreElements()) 
  72.         { 
  73.             String value = (String)e.nextElement(); 
  74.             System.out.println( "  PRM: '" + value + "' = '" + 
  75.                                 parms.getProperty( value ) + "'" ); 
  76.         } 
  77.  
  78.         return serveFile( uri, header, new File("."), true ); 
  79.     } 
  80.  
  81.     /** 
  82.      * HTTP response. 
  83.      * Return one of these from serve(). 
  84.      */ 
  85.     public class Response 
  86.     { 
  87.         /** 
  88.          * Default constructor: response = HTTP_OK, data = mime = 'null' 
  89.          */ 
  90.         public Response() 
  91.         { 
  92.             this.status = HTTP_OK; 
  93.         } 
  94.  
  95.         /** 
  96.          * Basic constructor. 
  97.          */ 
  98.         public Response( String status, String mimeType, InputStream data ) 
  99.         { 
  100.             this.status = status; 
  101.             this.mimeType = mimeType; 
  102.             this.data = data; 
  103.         } 
  104.  
  105.         /** 
  106.          * Convenience method that makes an InputStream out of 
  107.          * given text. 
  108.          */ 
  109.         public Response( String status, String mimeType, String txt ) 
  110.         { 
  111.             this.status = status; 
  112.             this.mimeType = mimeType; 
  113.             this.data = new ByteArrayInputStream( txt.getBytes()); 
  114.         } 
  115.  
  116.         /** 
  117.          * Adds given line to the header. 
  118.          */ 
  119.         public void addHeader( String name, String value ) 
  120.         { 
  121.             header.put( name, value ); 
  122.         } 
  123.  
  124.         /** 
  125.          * HTTP status code after processing, e.g. "200 OK", HTTP_OK 
  126.          */ 
  127.         public String status; 
  128.  
  129.         /** 
  130.          * MIME type of content, e.g. "text/html" 
  131.          */ 
  132.         public String mimeType; 
  133.  
  134.         /** 
  135.          * Data of the response, may be null. 
  136.          */ 
  137.         public InputStream data; 
  138.  
  139.         /** 
  140.          * Headers for the HTTP response. Use addHeader() 
  141.          * to add lines. 
  142.          */ 
  143.         public Properties header = new Properties(); 
  144.     } 
  145.  
  146.     /** 
  147.      * Some HTTP response status codes 
  148.      */ 
  149.     public static final String 
  150.         HTTP_OK = "200 OK"
  151.         HTTP_REDIRECT = "301 Moved Permanently"
  152.         HTTP_FORBIDDEN = "403 Forbidden"
  153.         HTTP_NOTFOUND = "404 Not Found"
  154.         HTTP_BADREQUEST = "400 Bad Request"
  155.         HTTP_INTERNALERROR = "500 Internal Server Error"
  156.         HTTP_NOTIMPLEMENTED = "501 Not Implemented"
  157.  
  158.     /** 
  159.      * Common mime types for dynamic content 
  160.      */ 
  161.     public static final String 
  162.         MIME_PLAINTEXT = "text/plain"
  163.         MIME_HTML = "text/html"
  164.         MIME_DEFAULT_BINARY = "application/octet-stream"
  165.  
  166.     // ================================================== 
  167.     // Socket & server code 
  168.     // ================================================== 
  169.  
  170.     /** 
  171.      * Starts a HTTP server to given port.<p> 
  172.      * Throws an IOException if the socket is already in use 
  173.      */ 
  174.     public NanoHTTPD( int port ) throws IOException 
  175.     { 
  176.         myTcpPort = port; 
  177.  
  178.         final ServerSocket ss = new ServerSocket( myTcpPort ); 
  179.         Thread t = new Thread( new Runnable() 
  180.             { 
  181.                 public void run() 
  182.                 { 
  183.                     try 
  184.                     { 
  185.                         whiletrue ) 
  186.                             new HTTPSession( ss.accept()); 
  187.                     } 
  188.                     catch ( IOException ioe ) 
  189.                     {} 
  190.                 } 
  191.             }); 
  192.         t.setDaemon( true ); 
  193.         t.start(); 
  194.     } 
  195.  
  196.     /** 
  197.      * Starts as a standalone file server and waits for Enter. 
  198.      */ 
  199.     public static void main( String[] args ) 
  200.     { 
  201.         System.out.println( "NanoHTTPD 1.11 (C) 2001,2005-2008 Jarno Elonen\n" + 
  202.                             "(Command line options: [port] [--licence])\n" ); 
  203.  
  204.         // Show licence if requested 
  205.         int lopt = -1
  206.         for ( int i=0; i<args.length; ++i ) 
  207.         if ( args[i].toLowerCase().endsWith( "licence" )) 
  208.         { 
  209.             lopt = i; 
  210.             System.out.println( LICENCE + "\n" ); 
  211.         } 
  212.  
  213.         // Change port if requested 
  214.         int port = 80
  215.         if ( args.length > 0 && lopt != 0 ) 
  216.             port = Integer.parseInt( args[0] ); 
  217.  
  218.         if ( args.length > 1 && 
  219.              args[1].toLowerCase().endsWith( "licence" )) 
  220.                 System.out.println( LICENCE + "\n" ); 
  221.  
  222.         NanoHTTPD nh = null
  223.         try 
  224.         { 
  225.             nh = new NanoHTTPD( port ); 
  226.         } 
  227.         catch( IOException ioe ) 
  228.         { 
  229.             System.err.println( "Couldn't start server:\n" + ioe ); 
  230.             System.exit( -1 ); 
  231.         } 
  232.         nh.myFileDir = new File(""); 
  233.  
  234.         System.out.println( "Now serving files in port " + port + " from \"" + 
  235.                             new File("").getAbsolutePath() + "\"" ); 
  236.         System.out.println( "Hit Enter to stop.\n" ); 
  237.  
  238.         try { System.in.read(); } catch( Throwable t ) {}; 
  239.     } 
  240.  
  241.     /** 
  242.      * Handles one session, i.e. parses the HTTP request 
  243.      * and returns the response. 
  244.      */ 
  245.     private class HTTPSession implements Runnable 
  246.     { 
  247.         public HTTPSession( Socket s ) 
  248.         { 
  249.             mySocket = s; 
  250.             Thread t = new Thread( this ); 
  251.             t.setDaemon( true ); 
  252.             t.start(); 
  253.         } 
  254.  
  255.         public void run() 
  256.         { 
  257.             try 
  258.             { 
  259.                 InputStream is = mySocket.getInputStream(); 
  260.                 if ( is == nullreturn
  261.                 BufferedReader in = new BufferedReader( new InputStreamReader( is )); 
  262.  
  263.                 // Read the request line 
  264.                 StringTokenizer st = new StringTokenizer( in.readLine()); 
  265.                 if ( !st.hasMoreTokens()) 
  266.                     sendError( HTTP_BADREQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html" ); 
  267.  
  268.                 String method = st.nextToken(); 
  269.  
  270.                 if ( !st.hasMoreTokens()) 
  271.                     sendError( HTTP_BADREQUEST, "BAD REQUEST: Missing URI. Usage: GET /example/file.html" ); 
  272.  
  273.                 String uri = st.nextToken(); 
  274.  
  275.                 // Decode parameters from the URI 
  276.                 Properties parms = new Properties(); 
  277.                 int qmi = uri.indexOf( '?' ); 
  278.                 if ( qmi >= 0 ) 
  279.                 { 
  280.                     decodeParms( uri.substring( qmi+1 ), parms ); 
  281.                     uri = decodePercent( uri.substring( 0, qmi )); 
  282.                 } 
  283.                 else uri = decodePercent(uri); 
  284.  
  285.  
  286.                 // If there's another token, it's protocol version, 
  287.                 // followed by HTTP headers. Ignore version but parse headers. 
  288.                 // NOTE: this now forces header names uppercase since they are 
  289.                 // case insensitive and vary by client. 
  290.                 Properties header = new Properties(); 
  291.                 if ( st.hasMoreTokens()) 
  292.                 { 
  293.                     String line = in.readLine(); 
  294.                     while ( line.trim().length() > 0 ) 
  295.                     { 
  296.                         int p = line.indexOf( ':' ); 
  297.                         header.put( line.substring(0,p).trim().toLowerCase(), line.substring(p+1).trim()); 
  298.                         line = in.readLine(); 
  299.                     } 
  300.                 } 
  301.  
  302.                 // If the method is POST, there may be parameters 
  303.                 // in data section, too, read it: 
  304.                 if ( method.equalsIgnoreCase( "POST" )) 
  305.                 { 
  306.                     long size = 0x7FFFFFFFFFFFFFFFl; 
  307.                     String contentLength = header.getProperty("content-length"); 
  308.                     if (contentLength != null
  309.                     { 
  310.                         try { size = Integer.parseInt(contentLength); } 
  311.                         catch (NumberFormatException ex) {} 
  312.                     } 
  313.                     String postLine = ""
  314.                     char buf[] = new char[512]; 
  315.                     int read = in.read(buf); 
  316.                     while ( read >= 0 && size > 0 && !postLine.endsWith("\r\n") ) 
  317.                     { 
  318.                         size -= read; 
  319.                         postLine += String.valueOf(buf, 0, read); 
  320.                         if ( size > 0 ) 
  321.                             read = in.read(buf); 
  322.                     } 
  323.                     postLine = postLine.trim(); 
  324.                     decodeParms( postLine, parms ); 
  325.                 } 
  326.  
  327.                 // Ok, now do the serve() 
  328.                 Response r = serve( uri, method, header, parms ); 
  329.                 if ( r == null ) 
  330.                     sendError( HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: Serve() returned a null response." ); 
  331.                 else 
  332.                     sendResponse( r.status, r.mimeType, r.header, r.data ); 
  333.  
  334.                 in.close(); 
  335.             } 
  336.             catch ( IOException ioe ) 
  337.             { 
  338.                 try 
  339.                 { 
  340.                     sendError( HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage()); 
  341.                 } 
  342.                 catch ( Throwable t ) {} 
  343.             } 
  344.             catch ( InterruptedException ie ) 
  345.             { 
  346.                 // Thrown by sendError, ignore and exit the thread. 
  347.             } 
  348.         } 
  349.  
  350.         /** 
  351.          * Decodes the percent encoding scheme. <br/> 
  352.          * For example: "an+example%20string" -> "an example string" 
  353.          */ 
  354.         private String decodePercent( String str ) throws InterruptedException 
  355.         { 
  356.             try 
  357.             { 
  358.                 StringBuffer sb = new StringBuffer(); 
  359.                 forint i=0; i<str.length(); i++ ) 
  360.                 { 
  361.                     char c = str.charAt( i ); 
  362.                     switch ( c ) 
  363.                     { 
  364.                         case '+'
  365.                             sb.append( ' ' ); 
  366.                             break
  367.                         case '%'
  368.                             sb.append((char)Integer.parseInt( str.substring(i+1,i+3), 16 )); 
  369.                             i += 2
  370.                             break
  371.                         default
  372.                             sb.append( c ); 
  373.                             break
  374.                     } 
  375.                 } 
  376.                 return new String( sb.toString().getBytes()); 
  377.             } 
  378.             catch( Exception e ) 
  379.             { 
  380.                 sendError( HTTP_BADREQUEST, "BAD REQUEST: Bad percent-encoding." ); 
  381.                 return null
  382.             } 
  383.         } 
  384.  
  385.         /** 
  386.          * Decodes parameters in percent-encoded URI-format 
  387.          * ( e.g. "name=Jack%20Daniels&pass=Single%20Malt" ) and 
  388.          * adds them to given Properties. 
  389.          */ 
  390.         private void decodeParms( String parms, Properties p ) 
  391.             throws InterruptedException 
  392.         { 
  393.             if ( parms == null ) 
  394.                 return
  395.  
  396.             StringTokenizer st = new StringTokenizer( parms, "&" ); 
  397.             while ( st.hasMoreTokens()) 
  398.             { 
  399.                 String e = st.nextToken(); 
  400.                 int sep = e.indexOf( '=' ); 
  401.                 if ( sep >= 0 ) 
  402.                     p.put( decodePercent( e.substring( 0, sep )).trim(), 
  403.                            decodePercent( e.substring( sep+1 ))); 
  404.             } 
  405.         } 
  406.  
  407.         /** 
  408.          * Returns an error message as a HTTP response and 
  409.          * throws InterruptedException to stop furhter request processing. 
  410.          */ 
  411.         private void sendError( String status, String msg ) throws InterruptedException 
  412.         { 
  413.             sendResponse( status, MIME_PLAINTEXT, nullnew ByteArrayInputStream( msg.getBytes())); 
  414.             throw new InterruptedException(); 
  415.         } 
  416.  
  417.         /** 
  418.          * Sends given response to the socket. 
  419.          */ 
  420.         private void sendResponse( String status, String mime, Properties header, InputStream data ) 
  421.         { 
  422.             try 
  423.             { 
  424.                 if ( status == null ) 
  425.                     throw new Error( "sendResponse(): Status can't be null." ); 
  426.  
  427.                 OutputStream out = mySocket.getOutputStream(); 
  428.                 PrintWriter pw = new PrintWriter( out ); 
  429.                 pw.print("HTTP/1.0 " + status + " \r\n"); 
  430.  
  431.                 if ( mime != null ) 
  432.                     pw.print("Content-Type: " + mime + "\r\n"); 
  433.  
  434.                 if ( header == null || header.getProperty( "Date" ) == null ) 
  435.                     pw.print( "Date: " + gmtFrmt.format( new Date()) + "\r\n"); 
  436.  
  437.                 if ( header != null ) 
  438.                 { 
  439.                     Enumeration e = header.keys(); 
  440.                     while ( e.hasMoreElements()) 
  441.                     { 
  442.                         String key = (String)e.nextElement(); 
  443.                         String value = header.getProperty( key ); 
  444.                         pw.print( key + ": " + value + "\r\n"); 
  445.                     } 
  446.                 } 
  447.  
  448.                 pw.print("\r\n"); 
  449.                 pw.flush(); 
  450.  
  451.                 if ( data != null ) 
  452.                 { 
  453.                     byte[] buff = new byte[2048]; 
  454.                     while (true
  455.                     { 
  456.                         int read = data.read( buff, 02048 ); 
  457.                         if (read <= 0
  458.                             break
  459.                         out.write( buff, 0, read ); 
  460.                     } 
  461.                 } 
  462.                 out.flush(); 
  463.                 out.close(); 
  464.                 if ( data != null ) 
  465.                     data.close(); 
  466.             } 
  467.             catch( IOException ioe ) 
  468.             { 
  469.                 // Couldn't write? No can do. 
  470.                 try { mySocket.close(); } catch( Throwable t ) {} 
  471.             } 
  472.         } 
  473.  
  474.         private Socket mySocket; 
  475.     }; 
  476.  
  477.     /** 
  478.      * URL-encodes everything between "/"-characters. 
  479.      * Encodes spaces as '%20' instead of '+'. 
  480.      */ 
  481.     private String encodeUri( String uri ) 
  482.     { 
  483.         String newUri = ""
  484.         StringTokenizer st = new StringTokenizer( uri, "/ "true ); 
  485.         while ( st.hasMoreTokens()) 
  486.         { 
  487.             String tok = st.nextToken(); 
  488.             if ( tok.equals( "/" )) 
  489.                 newUri += "/"
  490.             else if ( tok.equals( " " )) 
  491.                 newUri += "%20"
  492.             else 
  493.             { 
  494.                 newUri += URLEncoder.encode( tok ); 
  495.                 // For Java 1.4 you'll want to use this instead: 
  496.                 // try { newUri += URLEncoder.encode( tok, "UTF-8" ); } catch ( UnsupportedEncodingException uee ) 
  497.             } 
  498.         } 
  499.         return newUri; 
  500.     } 
  501.  
  502.     private int myTcpPort; 
  503.     File myFileDir; 
  504.  
  505.     // ================================================== 
  506.     // File server code 
  507.     // ================================================== 
  508.  
  509.     /** 
  510.      * Serves file from homeDir and its' subdirectories (only). 
  511.      * Uses only URI, ignores all headers and HTTP parameters. 
  512.      */ 
  513.     public Response serveFile( String uri, Properties header, File homeDir, 
  514.                                boolean allowDirectoryListing ) 
  515.     { 
  516.         // Make sure we won't die of an exception later 
  517.         if ( !homeDir.isDirectory()) 
  518.             return new Response( HTTP_INTERNALERROR, MIME_PLAINTEXT, 
  519.                                  "INTERNAL ERRROR: serveFile(): given homeDir is not a directory." ); 
  520.  
  521.         // Remove URL arguments 
  522.         uri = uri.trim().replace( File.separatorChar, '/' ); 
  523.         if ( uri.indexOf( '?' ) >= 0 ) 
  524.             uri = uri.substring(0, uri.indexOf( '?' )); 
  525.  
  526.         // Prohibit getting out of current directory 
  527.         if ( uri.startsWith( ".." ) || uri.endsWith( ".." ) || uri.indexOf( "../" ) >= 0 ) 
  528.             return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT, 
  529.                                  "FORBIDDEN: Won't serve ../ for security reasons." ); 
  530.  
  531.         File f = new File( homeDir, uri ); 
  532.         if ( !f.exists()) 
  533.             return new Response( HTTP_NOTFOUND, MIME_PLAINTEXT, 
  534.                                  "Error 404, file not found." ); 
  535.  
  536.         // List the directory, if necessary 
  537.         if ( f.isDirectory()) 
  538.         { 
  539.             // Browsers get confused without '/' after the 
  540.             // directory, send a redirect. 
  541.             if ( !uri.endsWith( "/" )) 
  542.             { 
  543.                 uri += "/"
  544.                 Response r = new Response( HTTP_REDIRECT, MIME_HTML, 
  545.                                            "<html><body>Redirected: <a href=\"" + uri + "\">" + 
  546.                                            uri + "</a></body></html>"); 
  547.                 r.addHeader( "Location", uri ); 
  548.                 return r; 
  549.             } 
  550.  
  551.             // First try index.html and index.htm 
  552.             if ( new File( f, "index.html" ).exists()) 
  553.                 f = new File( homeDir, uri + "/index.html" ); 
  554.             else if ( new File( f, "index.htm" ).exists()) 
  555.                 f = new File( homeDir, uri + "/index.htm" ); 
  556.  
  557.             // No index file, list the directory 
  558.             else if ( allowDirectoryListing ) 
  559.             { 
  560.                 String[] files = f.list(); 
  561.                 String msg = "<html><body><h1>Directory " + uri + "</h1><br/>"
  562.  
  563.                 if ( uri.length() > 1 ) 
  564.                 { 
  565.                     String u = uri.substring( 0, uri.length()-1 ); 
  566.                     int slash = u.lastIndexOf( '/' ); 
  567.                     if ( slash >= 0 && slash  < u.length()) 
  568.                         msg += "<b><a href=\"" + uri.substring(0, slash+1) + "\">..</a></b><br/>"
  569.                 } 
  570.  
  571.                 for ( int i=0; i<files.length; ++i ) 
  572.                 { 
  573.                     File curFile = new File( f, files[i] ); 
  574.                     boolean dir = curFile.isDirectory(); 
  575.                     if ( dir ) 
  576.                     { 
  577.                         msg += "<b>"
  578.                         files[i] += "/"
  579.                     } 
  580.  
  581.                     msg += "<a href=\"" + encodeUri( uri + files[i] ) + "\">" + 
  582.                            files[i] + "</a>"
  583.  
  584.                     // Show file size 
  585.                     if ( curFile.isFile()) 
  586.                     { 
  587.                         long len = curFile.length(); 
  588.                         msg += " &nbsp;<font size=2>("
  589.                         if ( len < 1024 ) 
  590.                             msg += curFile.length() + " bytes"
  591.                         else if ( len < 1024 * 1024 ) 
  592.                             msg += curFile.length()/1024 + "." + (curFile.length()%1024/10%100) + " KB"
  593.                         else 
  594.                             msg += curFile.length()/(1024*1024) + "." + curFile.length()%(1024*1024)/10%100 + " MB"
  595.  
  596.                         msg += ")</font>"
  597.                     } 
  598.                     msg += "<br/>"
  599.                     if ( dir ) msg += "</b>"
  600.                 } 
  601.                 return new Response( HTTP_OK, MIME_HTML, msg ); 
  602.             } 
  603.             else 
  604.             { 
  605.                 return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT, 
  606.                                  "FORBIDDEN: No directory listing." ); 
  607.             } 
  608.         } 
  609.  
  610.         try 
  611.         { 
  612.             // Get MIME type from file name extension, if possible 
  613.             String mime = null
  614.             int dot = f.getCanonicalPath().lastIndexOf( '.' ); 
  615.             if ( dot >= 0 ) 
  616.                 mime = (String)theMimeTypes.get( f.getCanonicalPath().substring( dot + 1 ).toLowerCase()); 
  617.             if ( mime == null ) 
  618.                 mime = MIME_DEFAULT_BINARY; 
  619.  
  620.             // Support (simple) skipping: 
  621.             long startFrom = 0
  622.             String range = header.getProperty( "Range" ); 
  623.             if ( range != null ) 
  624.             { 
  625.                 if ( range.startsWith( "bytes=" )) 
  626.                 { 
  627.                     range = range.substring( "bytes=".length()); 
  628.                     int minus = range.indexOf( '-' ); 
  629.                     if ( minus > 0 ) 
  630.                         range = range.substring( 0, minus ); 
  631.                     try { 
  632.                         startFrom = Long.parseLong( range ); 
  633.                     } 
  634.                     catch ( NumberFormatException nfe ) {} 
  635.                 } 
  636.             } 
  637.  
  638.             FileInputStream fis = new FileInputStream( f ); 
  639.             fis.skip( startFrom ); 
  640.             Response r = new Response( HTTP_OK, mime, fis ); 
  641.             r.addHeader( "Content-length""" + (f.length() - startFrom)); 
  642.             r.addHeader( "Content-range""" + startFrom + "-" + 
  643.                         (f.length()-1) + "/" + f.length()); 
  644.             return r; 
  645.         } 
  646.         catch( IOException ioe ) 
  647.         { 
  648.             return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: Reading file failed." ); 
  649.         } 
  650.     } 
  651.  
  652.     /** 
  653.      * Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE 
  654.      */ 
  655.     private static Hashtable theMimeTypes = new Hashtable(); 
  656.     static 
  657.     { 
  658.         StringTokenizer st = new StringTokenizer( 
  659.             "htm        text/html "
  660.             "html       text/html "
  661.             "txt        text/plain "
  662.             "asc        text/plain "
  663.             "gif        image/gif "
  664.             "jpg        image/jpeg "
  665.             "jpeg       image/jpeg "
  666.             "png        image/png "
  667.             "mp3        audio/mpeg "
  668.             "m3u        audio/mpeg-url " + 
  669.             "pdf        application/pdf "
  670.             "doc        application/msword "
  671.             "ogg        application/x-ogg "
  672.             "zip        application/octet-stream "
  673.             "exe        application/octet-stream "
  674.             "class      application/octet-stream " ); 
  675.         while ( st.hasMoreTokens()) 
  676.             theMimeTypes.put( st.nextToken(), st.nextToken()); 
  677.     } 
  678.  
  679.     /** 
  680.      * GMT date formatter 
  681.      */ 
  682.     private static java.text.SimpleDateFormat gmtFrmt; 
  683.     static 
  684.     { 
  685.         gmtFrmt = new java.text.SimpleDateFormat( "E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US); 
  686.         gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT")); 
  687.     } 
  688.  
  689.     /** 
  690.      * The distribution licence 
  691.      */ 
  692.     private static final String LICENCE = 
  693.         "Copyright (C) 2001,2005-2008 by Jarno Elonen <elonen@iki.fi>\n"
  694.         "\n"
  695.         "Redistribution and use in source and binary forms, with or without\n"
  696.         "modification, are permitted provided that the following conditions\n"
  697.         "are met:\n"
  698.         "\n"
  699.         "Redistributions of source code must retain the above copyright notice,\n"
  700.         "this list of conditions and the following disclaimer. Redistributions in\n"
  701.         "binary form must reproduce the above copyright notice, this list of\n"
  702.         "conditions and the following disclaimer in the documentation and/or other\n"
  703.         "materials provided with the distribution. The name of the author may not\n"
  704.         "be used to endorse or promote products derived from this software without\n"
  705.         "specific prior written permission. \n"
  706.         " \n"
  707.         "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
  708.         "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"
  709.         "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
  710.         "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
  711.         "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
  712.         "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
  713.         "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
  714.         "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
  715.         "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
  716.         "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."

 

被阅809次, 0投一票NanoHTTPD
  • 看完了要说点啥么?
  • 昵称 (不填说不了话)
  • 信箱地址 (不会被公开,但是不填也说不了话)
  • 网址 (这个不填也成)
Powered by MiniBoke v2.0.0.8 Build 0828

Copyright © 2008 开源吧!. All rights reserved.

粤ICP备07500939号