2014-12-04 48 views
1

我使用Python 2.7.8從我可以下載文件的位置製作服務器。問題在於許多文件包含utf-8字符,如čćžšđ等。我嘗試瞭解碼路徑,但每當我用unicode字符點擊文件名時,它都會返回「錯誤404:找不到文件」。如何正確解碼路徑,以便可以下載具有utf-8字符的文件,並且如果可能的話,將它們顯示爲我服務器索引上的utf-8字符。這裏是我的服務器的代碼,其中包括我試過的和完整的服務器代碼:使用Python中的BaseHTTPServer從UnicodeHTTPServer下載文件

# -*- coding: utf-8 -*- 

__version__ = "0.6" 

__all__ = ["SimpleHTTPRequestHandler"] 

import os 
import posixpath 
import BaseHTTPServer 
import urllib 
import cgi 
import shutil 
import mimetypes 
from StringIO import StringIO 
import SocketServer 
import time 
import sys 
import unicodedata 



class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 

    server_version = "SimpleHTTP/" + __version__ 

    def do_GET(self): 
     """Serve a GET request.""" 
     f = self.send_head() 
     if f: 
     self.copyfile(f, self.wfile) 
     f.close() 

    def do_HEAD(self): 
     """Serve a HEAD request.""" 
     f = self.send_head() 
     if f: 
      f.close() 

    def send_head(self): 
     path_now = self.translate_path(self.path) 
     path_change = (os.path.dirname(os.path.abspath(__file__)) + "/files/") 
     if path_now.startswith("/home/files/"): 
      pass 
     else: 
      os.chdir(path_change) 
     path = self.translate_path(self.path) 
     """Those are few examples of what have I tried: 
     path = path1.decode('ascii', 'ignore').makePath() 
     path = unicodedata.normalize('NFKD', path1).encode('ascii','ignore') 
     path2 = path1.decode("utf-8") 
     path = path2.encode("utf-8") 
     path = path2.encode("utf-8")""" 
     f = None 
     if os.path.isdir(path): 
      for index in "index.html", "index.htm": 
       index = os.path.join(path, index) 
       if os.path.exists(index): 
        path = index 
        break 
      else: 
       return self.list_directory(path) 
     ctype = self.guess_type(path) 
     if ctype.startswith('text/'): 
      mode = 'r' 
     else: 
      mode = 'rb' 
     try: 
      f = open(path.decode(sys.getfilesystemencoding()), mode) #this doesn't work, nothing changes 
      size = os.path.getsize(path) 
     except IOError: 
      self.send_error(404, "File not found") 
      return None 
     self.send_response(200) 
     self.send_header("Content-type", ctype + "; charset=utf-8") # + " charset=utf-8" 
     self.send_header("Content-Length", size) 
     self.end_headers() 
     return f 

    def list_directory(self, path): 
     try: 
      list = os.listdir(path) 
     except os.error: 
      self.send_error(404, "No permission to list directory") 
      return None 
     list.sort(lambda a, b: cmp(a.lower(), b.lower())) 
     f = StringIO() 
     f.write("<title>Directory listing for %s</title>\n" % self.path) 
     f.write("<h2>Directory listing for %s</h2>\n" % self.path) 
     f.write("<hr>\n<ul>\n") 
     for name in list: 
      fullname = os.path.join(path, name) 
      displayname = linkname = name = cgi.escape(name) 
      if os.path.isdir(fullname): 
       displayname = name + "/" 
       linkname = name + "/" 
      if os.path.islink(fullname): 
       displayname = name + "@" 
      f.write('<li><a href="%s">%s</a>\n' % (linkname, displayname)) 
     f.write("</ul>\n<hr>\n") 
     f.seek(0) 
     self.send_response(200) 
     self.send_header("Content-type", "text/html") 
     self.end_headers() 
     return f 

    def translate_path(self, path): 
     try: 
      path = posixpath.normpath(urllib.unquote(path)) 
      words = path.split('/') 
      words = filter(None, words) 
      path = os.getcwd() 
      for word in words: 
       drive, word = os.path.splitdrive(word) 
       head, word = os.path.split(word) 
       if word in (os.curdir, os.pardir): continue 
       path = os.path.join(path, word) 
      return path 
     except Exception, e: 
      self.send_error(403, e) 
      path = posixpath.normpath(urllib.unquote(path)) 
      words = path.split('/') 
      words = filter(None, words) 
      path = os.getcwd() 
      for word in words: 
       drive, word = os.path.splitdrive(word) 
       head, word = os.path.split(word) 
       if word in (os.curdir, os.pardir): continue 
       path = os.path.join(path, word) 
      return path.encode("utf-8") 

    def copyfile(self, source, outputfile): 
     shutil.copyfileobj(source, outputfile) 

    def guess_type(self, path): 
     base, ext = posixpath.splitext(path) 
     if self.extensions_map.has_key(ext): 
      return self.extensions_map[ext] 
     ext = ext.lower() 
     if self.extensions_map.has_key(ext): 
      return self.extensions_map[ext] 
     else: 
      return self.extensions_map[''] 

    extensions_map = mimetypes.types_map.copy() 
    extensions_map.update({ 
     '': 'application/octet-stream', # Default 
     '.py': 'text/plain', 
     '.c': 'text/plain', 
     '.h': 'text/plain', 
     }) 

class ForkingHTTPServer(SocketServer.ForkingMixIn, BaseHTTPServer.HTTPServer): 
    def finish_request(self, request, client_address): 
     request.settimeout(30) 
     BaseHTTPServer.HTTPServer.finish_request(self, request, client_address) 


def test(HandlerClass = SimpleHTTPRequestHandler, ServerClass = BaseHTTPServer.HTTPServer, server_address=("192.168.1.2", 8000)): 
    try: 
     print "Server started" 
     srvr = ForkingHTTPServer(server_address, HandlerClass) 
     srvr.serve_forever() # serve_forever 
    except KeyboardInterrupt: 
     print "Closing sockets..." 
     time.sleep(2) 
     print "Server is shutting down in 3" 
     time.sleep(1) 
     print "Server is shutting down in 2" 
     time.sleep(1) 
     print "Server is shutting down in 1" 
     time.sleep(1) 
     srvr.socket.close() 


if __name__ == '__main__': 
     test() 

我希望這是您需要的所有信息。如果您還需要別的什麼,只是評論,我會很高興編輯我的問題;)

回答

1

我剛纔看到我設置的字符集爲UTF-8內部「send_head」的功能,而不是在「list_directory」功能。另外,我編輯

"; charset=utf-8" 

'; charset="utf-8"' 

,它現在就像一個魅力。

它看起來像我一直在編碼/解碼righ的東西,但沒有設置我的標題正確。