Python BaseHTTPServer 通过 curl 发送保存文件

Posted

技术标签:

【中文标题】Python BaseHTTPServer 通过 curl 发送保存文件【英文标题】:Python BaseHTTPServer Save file send by curl 【发布时间】:2015-03-30 15:07:54 【问题描述】:

我有下一个 python 代码:

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os

PORT_NUMBER = 8080

#This class will handles any incoming request from
#the browser
class myHandler(BaseHTTPRequestHandler):

    store_path = os.path.dirname(os.path.realpath(__file__)) + '\copyFile'
    print store_path
    # handler for the GET requests
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text/html')
        self.end_headers()
        # Send the html message
        self.wfile.write("Hello World !")
        return

    # handeler for POST request
    def do_POST(self):
        length = self.headers['content-length']
        data = self.rfile.read(int(length))
        with open(self.store_path, 'w') as fh:
            fh.write(data.decode())

        self.send_response(200)

try:
    #Create a web server and define the handler to manage the
    #incoming request
    server = HTTPServer(('', PORT_NUMBER), myHandler)
    print 'Started httpserver on port ' , PORT_NUMBER

    #Wait forever for incoming htto requests
    server.serve_forever()

except KeyboardInterrupt:
    print '^C received, shutting down the web server'
server.socket.close()

我正在尝试制作一个简单的 python 网络服务器来保存发布到本地路径的文件。我正在使用curl 将文件发送到服务器,其中包含以下行:curl -F file="myfile.txt" http://localhost:8080

结果不符合我的预期:

--------------------------e6929774a41d68c0

Content-Disposition: form-data; name="file"



myfile.txt

--------------------------e6929774a41d68c0--

我能做些什么来解决这个问题?

我检查了this link,但没有帮助:(

【问题讨论】:

我认为这正是您使用 curl 的方式。查看 curl 手册页以了解 -F 的作用以了解更多详细信息。但我相信你只需要这样做:curl -F "file=@myfile.txt" http://localhost:8080。 @ 读取并发送文件的内容,而不仅仅是像 curl 命令那样的文件名。 现在它显示了文件中的所有文本,但我还有一些额外的东西:Content-Disposition、Content-Type 和 -----<code> 的东西 【参考方案1】:

好的,这里发生的事情是您已经启动了 HTTPServer,它创建了一个用于侦听传入连接的线程。当它获得一个有效的连接时,它会创建一个请求处理程序的实例,该处理程序将根据传入连接的输入调用适当的方法。

BaseHTTPRequestHandler 将在后台处理传入的数据,并为您提供一些有用的变量来访问数据。发送的数据是从标准输入中检索的。因为 BaseHTTPRequestHandler 是相当基本的,它只会为你做这么多。来自该流的原始数据可以在 self.rfile 对象中找到。这是您会发现查询字符串、JSON 或二进制文件的地方。

现在您可以编写自己的解析器来检索这些数据,但这可能很复杂,并且已经有模块可以帮助您解决这个问题。有一个名为 cgi 的标准 Python 模块可以让您更轻松地完成此操作。你可以找到关于这个模块的信息here。

您需要执行以下操作来检索您的文件:

import cgi

...

class myHandler(BaseHTTPRequestHandler):

    ...

    def do_POST(self):
        form = cgi.FieldStorage(
                 fp=self.rfile,
                 headers=self.headers,
                 environ="REQUEST_METHOD": "POST",
                          "CONTENT_TYPE": self.headers['Content-Type'])

         uploaded_file = form.getvalue("file")
         if uploaded_file:
             with open(self.store_path, "wb") as fh:
                 fh.write(uploaded_file.file.read())

        ...

BaseHTTPRequestHandler 实际上不会为您解析 POST 中的数据,因此我们需要向 FieldStorage 对象提供正确解析数据所需的信息。我们需要向它提供包含原始数据和请求中包含的标头的文件。我们还需要为它提供有关请求的详细信息的环境,因为 BaseHTTPRequestHandler 不解析 POST 这些变量没有添加到默认环境中,这就是我们创建自己的字典的原因。我会考虑看看CGIHTTPServer,它将封装一些这种行为。

创建表单后,我们可以使用“安全”getter 来检索我们的数据。如果关键字不存在,则此方法将返回 None。您还可以使用以下方式检索数据:

try:
    uploaded_file = form['file']

except KeyError:
    # The 'file' parameter was missing.
    # Respond to the client with an error...
    ...

这两种方法都返回 FieldStorage 或 MiniFieldStorage 对象。这些细节可以在 cgi 模块的链接中找到。但是 Python 中的一个杀手级功能是 help 方法。例如

import cgi
help(cgi.FieldStorage)

这将列出一个手册页,其中提供了您需要了解的有关 FieldStorage 对象的所有详细信息。

附带说明,在 Python 中构建路径时,您最好使用 os.path.join() 为您正在运行的系统安全地创建有效路径。所以,而不是有这条线:

store_path = os.path.dirname(os.path.realpath(__file__)) + '\copyFile'

我会将其替换为:

store_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'copyFile')

【讨论】:

以上是关于Python BaseHTTPServer 通过 curl 发送保存文件的主要内容,如果未能解决你的问题,请参考以下文章

BaseHTTPServer 和 SimpleHTTPServer 有啥区别?何时何地使用它们?

python SimpleHTTPServer源码学习

BaseHTTPServer和SimpleHTTPServer有什么区别?何时何地使用它们?

python简易web服务器学习笔记

Python实现简单的Web服务器 解析

python简易web服务器学习笔记