自定义python web服务器中响应的png图像

自定义python web服务器中响应的png图像,python,sockets,webserver,Python,Sockets,Webserver,我正在用python编写一个简单的Web服务器,并且已经成功地做到了这一点。我能够在javascript文件中呈现html页面,但无法呈现图像 一些相关的代码 def createResponse(self, data):#, last_modified=0): # print data response_code = data[0] mimetype = data[1][1] data = data[1][0]

我正在用python编写一个简单的Web服务器,并且已经成功地做到了这一点。我能够在javascript文件中呈现html页面,但无法呈现图像

一些相关的代码

def createResponse(self, data):#, last_modified=0):
        # print data
        response_code = data[0]
        mimetype  = data[1][1]
        data = data[1][0]               # (200, (data, mimetype))

        res = "HTTP/1.0 " + self.config['STATUS_STRING'][str(response_code)] + "\r\n"
        res += "Content-Type: " + mimetype + "\r\n"
        res += "Date: " + strftime("%a, %d %b %Y %X GMT", gmtime()) + "\r\n"
        # if last_modified:
        #     res += "Last Modified: " + last_modified + "\r\n"
        res += 'Server: ' + self.config['SERVER_NAME'] + "\r\n"
        res += 'Connection: close' + '\r\n'  # signal that the conection wil be closed after complting the request
        res += "\r\n"
        res += data

        return res.encode("utf8")

def _handleGET(self, path):
    # some stuff, then
    # File exists and read permission, so give file
    try:
        fp = open(filepath, "rb")
    except IOError as e:
        if e.errno == errno.EACCES:
            return (500, self._readFile(self.config['ERROR_DIR'] + '/' + str(500) + ".html"));
        # Not a permission error.
        raise
    else:
        with fp:
            return (200, (fp.read().decode("utf8"), mimetypes.guess_type(filepath)[0])) # return (200,(data,mimetype))
我为客户端创建了一个套接字,然后使用它返回响应

clientSocket.sendall(self.createResponse(self._handleGET(data)))
我用utf8编码整个响应,它是一个字符串。这适用于html页面、js文件和css文件,但不适用于图像。(png、gif等)。我尝试设置标题,并用base64二进制编码图像的响应等,但我无法实现

  • 有什么建议吗
  • 这是可能的,因为现在我认为使用这种方法渲染图像是不可能的,因为头部将在
    utf8
    中,而图像的内容将在其他编码中。所以它们不能连接在一起。如果我错了,请纠正我

    • http的头不是编码的,应该是纯ASCII。内容部分是任何二进制数据。对于文本,可以在
      内容类型中指定编码。
      因此,
      createResponse
      必须单独处理文本和二进制数据,可能使用显式编码参数:

      def create_response(self, content, response_code=200, mimetype='text/html', encoding='UTF-8', additional_params=None):
          header_params = {
              'Content-Type', '%s; charset=%s' %(mimetype, encoding) if encoding else mimetype,
              'Date': strftime("%a, %d %b %Y %X GMT", gmtime()),
              'Server': self.config['SERVER_NAME'],
              'Connection': 'close',
          }
          if additional_params:
              header_params.update(additional_params)
      
          if encoding:
              content = content.encode(encoding)
      
          header = "HTTP/1.0 %s\r\n%s\r\n" % (
              self.config['STATUS_STRING'][str(response_code)],
              ''.join('%s: %s\r\n' % kv for kv in header_params.iteritems())
          )
          return header.encode('utf8') + content
      
      用于:

          with fp:
              return self.create_response(fp.read(), mime_type=mimetypes.guess_type(filepath)[0], encoding=None)
      

      http的头不是编码的,应该是纯ASCII。内容部分是任何二进制数据。对于文本,可以在
      内容类型中指定编码。
      因此,
      createResponse
      必须单独处理文本和二进制数据,可能使用显式编码参数:

      def create_response(self, content, response_code=200, mimetype='text/html', encoding='UTF-8', additional_params=None):
          header_params = {
              'Content-Type', '%s; charset=%s' %(mimetype, encoding) if encoding else mimetype,
              'Date': strftime("%a, %d %b %Y %X GMT", gmtime()),
              'Server': self.config['SERVER_NAME'],
              'Connection': 'close',
          }
          if additional_params:
              header_params.update(additional_params)
      
          if encoding:
              content = content.encode(encoding)
      
          header = "HTTP/1.0 %s\r\n%s\r\n" % (
              self.config['STATUS_STRING'][str(response_code)],
              ''.join('%s: %s\r\n' % kv for kv in header_params.iteritems())
          )
          return header.encode('utf8') + content
      
      用于:

          with fp:
              return self.create_response(fp.read(), mime_type=mimetypes.guess_type(filepath)[0], encoding=None)
      


      不要试图自己编写http服务器。使用像flask或bottle这样的框架。显然,预先制作好的服务器会更好,但不管怎样,自己编写一个基本的框架来了解服务器背后的情况是一种很好的学习体验scenes@PinkeshBadjatiya我很好奇。为什么要将
      self
      作为参数传递给
      \u handleGET
      ?实例方法已经传递了
      self
      ,因此只需执行
      self.\u handleGET(data)
      。@Daniel是的,您是正确的。但我想学习和理解事物是如何运作的,而且这会很有趣。另外,我的主要目的是了解套接字以及不同的应用程序如何使用它们。@AkshatMahajan抱歉,这是一个打字错误。谢谢你指出。更正!!不要试图自己编写http服务器。使用像flask或bottle这样的框架。显然,预先制作好的服务器会更好,但不管怎样,自己编写一个基本的框架来了解服务器背后的情况是一种很好的学习体验scenes@PinkeshBadjatiya我很好奇。为什么要将
      self
      作为参数传递给
      \u handleGET
      ?实例方法已经传递了
      self
      ,因此只需执行
      self.\u handleGET(data)
      。@Daniel是的,您是正确的。但我想学习和理解事物是如何运作的,而且这会很有趣。另外,我的主要目的是了解套接字以及不同的应用程序如何使用它们。@AkshatMahajan抱歉,这是一个打字错误。谢谢你指出。更正!!但是,当我想要呈现png图像时,返回的内容应该是什么?它应该是二进制的吗?我正在尝试你建议的mp3文件,但它不起作用。我只是使用
      data=fp.read()
      以二进制格式打开文件来读取mp3数据。然后将响应返回为
      header+data
      ,但它会出现以下错误
      UnicodeDecodeError:“ascii”编解码器无法解码第21位的字节0xff:ordinal不在范围(128)
      ,因此您有utf8字符串。代码已更正。我的代码工作正常,就是删除行content=content.encode(encoding)。我收到错误
      UnicodeDecodeError:“ascii”编解码器无法解码位置27处的字节0xbf:序号不在范围(128)
      。因为内容是二进制的,所以我从代码中删除了这一行。如果我遗漏了什么,请更正。但是,当我要渲染png图像时,返回的内容应该是什么?它应该是二进制的吗?我正在尝试你建议的mp3文件,但它不起作用。我只是使用
      data=fp.read()
      以二进制格式打开文件来读取mp3数据。然后将响应返回为
      header+data
      ,但它会出现以下错误
      UnicodeDecodeError:“ascii”编解码器无法解码第21位的字节0xff:ordinal不在范围(128)
      ,因此您有utf8字符串。代码已更正。我的代码工作正常,就是删除行content=content.encode(encoding)。我收到错误
      UnicodeDecodeError:“ascii”编解码器无法解码位置27处的字节0xbf:序号不在范围(128)
      。因为内容是二进制的,所以我从代码中删除了这一行。如果我遗漏了什么,请更正。