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 有啥区别?何时何地使用它们?