【问题标题】:Simple Python Webserver to save file简单的 Python Webserver 来保存文件
【发布时间】:2023-03-24 12:59:01
【问题描述】:

我正在尝试制作一个简单的 python 网络服务器,以将 Posted 的文本保存到名为 store.json 的文件中,该文件与 python 脚本位于同一文件夹中。这是我的一半代码,谁能告诉我剩下的应该是什么?

import string,cgi,time
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
#import pri

class StoreHandler(BaseHTTPRequestHandler):
def do_GET(self):
    try:
        if self.path == "/store.json":
            f = open(curdir + sep + "store.json") #self.path has /test.html
            self.send_response(200)
            self.send_header('Content-type','text/json')
            self.end_headers()
            self.wfile.write(f.read())
            f.close()
            return
        return
    except IOError:
        self.send_error(404,'File Not Found: %s' % self.path)
def do_POST(self):
    //if the url is 'store.json' then
    //what do I do here?

def main():
    try:
        server = HTTPServer(('', 80), StoreHandler)
        print 'started...'
        server.serve_forever()
    except KeyboardInterrupt:
        print '^C received, shutting down server'
        server.socket.close()
if __name__ == '__main__':
    main()

【问题讨论】:

  • API 可以并行调用,如何避免文件读/写的竞争条件?

标签: python-3.x webserver


【解决方案1】:

大致思路如下:

from os import curdir
from os.path import join as pjoin

from http.server import BaseHTTPRequestHandler, HTTPServer

class StoreHandler(BaseHTTPRequestHandler):
    store_path = pjoin(curdir, 'store.json')

    def do_GET(self):
        if self.path == '/store.json':
            with open(self.store_path) as fh:
                self.send_response(200)
                self.send_header('Content-type', 'text/json')
                self.end_headers()
                self.wfile.write(fh.read().encode())

    def do_POST(self):
        if self.path == '/store.json':
            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)


server = HTTPServer(('', 8080), StoreHandler)
server.serve_forever()
$ curl -X POST --data "one two three four" localhost:8080/store.json
$ curl -X GET localhost:8080/store.json    
one two three four%

【讨论】:

  • 好的,你需要把from BaseHTTPServer改成from http.server
  • 抱歉,没有注意到标签的-3.x 部分。
  • 我发现的另一件事是您必须将'rb' 作为参数添加到 open 命令,否则会出现类型异常。 With open(self.store_path,'rb') as fh:
  • 好的,我把违规行改成了self.headers['content-length']。我还必须将 post open 更改为 'wb'
  • @SomethingSomething 是的。删除content type 行,删除decode() 和encode() 并使用wb 和rb 而不是w 和(无)。
【解决方案2】:

重要的是您必须从原始发布的数据中正确构建cgi.FieldStorage,例如

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

之后很容易转储文件,这是一个简单的处理程序,它在do_GET 上显示一个表单,用于上传用户选择的任何文件,并在表单发布时将该文件保存到do_POST 中的/tmp

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler

import cgi

class StoreHandler(BaseHTTPRequestHandler):
    def do_POST(self):

        form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={'REQUEST_METHOD':'POST',
                     'CONTENT_TYPE':self.headers['Content-Type'],
                     })
        filename = form['file'].filename
        data = form['file'].file.read()
        open("/tmp/%s"%filename, "wb").write(data)

        self.respond("uploaded %s, thanks"%filename)

    def do_GET(self):
        response = """
        <html><body>
        <form enctype="multipart/form-data" method="post">
        <p>File: <input type="file" name="file"></p>
        <p><input type="submit" value="Upload"></p>
        </form>
        </body></html>
        """        

        self.respond(response)

    def respond(self, response, status=200):
        self.send_response(status)
        self.send_header("Content-type", "text/html")
        self.send_header("Content-length", len(response))
        self.end_headers()
        self.wfile.write(response)  

另请注意,self.respond 不是标准方法,我只是添加它以快速返回一些响应。

【讨论】:

  • 这是 Python 3,SimpleHTTP 还能工作吗?抱歉,我没有提到这一点。
  • @ArlenBeiler 如果它适用于 python3,我已更改为 BaseHTTPRequestHandler,python3 中似乎也有 SimplreREquestHandler docs.python.org/3.3/library/…
  • 上传表单后对我来说['file'].file is None
  • API 可以并行调用,这样写文件安全吗?
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 2014-01-23
  • 1970-01-01
  • 2018-02-25
  • 2013-10-05
  • 1970-01-01
  • 2016-04-10
  • 1970-01-01
相关资源
最近更新 更多