3

まず、twisted.webフレームワークを使用しています。Twisted.webのファイルアップロードは、私が望んでいたように機能しませんでした(ファイルデータのみが含まれ、他の情報は含まれてcgi.parse_multipartいません)、私が望むように機能しません(同じこと、twisted.webこの関数を使用します)、機能cgi.FieldStorageしませんでした(CGIインターフェイスではなくツイストを介してPOSTデータを取得しているため、私が知る限り、FieldStoragestdinを介してリクエストを取得しようとします)、混乱して激怒しtwisted.web2たため、機能しませんでしたDeferred(私が欲しいものには複雑すぎます)。

そうは言っても、私は自分でHTTPリクエストを解析してみることにしました。

Chromeを使用すると、HTTPリクエストは次のように形成されます。

------WebKitFormBoundary7fouZ8mEjlCe92pq
Content-Disposition: form-data; name="upload_file_nonce"

11b03b61-9252-11df-a357-00266c608adb
------WebKitFormBoundary7fouZ8mEjlCe92pq
Content-Disposition: form-data; name="file"; filename="login.html"
Content-Type: text/html

<!DOCTYPE html>
<html>
  <head> 

...

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


------WebKitFormBoundary7fouZ8mEjlCe92pq--

これは常にそれが形成される方法ですか?私はそれを次のような正規表現で解析しています(コードの壁を許してください):

(注:コードの大部分を切り取って、関連性があると思われるものだけを表示しました(正規表現(ええ、ネストされた括弧)、これは私が作成__init__したクラスのメソッド(これまでのところ唯一のメソッド)Uploadsです。完全なコードは改訂履歴に表示されます(括弧が一致していなかったと思います)

if line == "--{0}--".format(boundary):
    finished = True

if in_header == True and not line:
    in_header = False
    if 'type' not in current_file:
        ignore_current_file = True

if in_header == True:
    m = re.match(
        "Content-Disposition: form-data; name=\"(.*?)\"; filename=\"(.*?)\"$", line)
    if m:
        input_name, current_file['filename'] = m.group(1), m.group(2)

    m = re.match("Content-Type: (.*)$", line)
    if m:
        current_file['type'] = m.group(1)

    else:
        if 'data' not in current_file:
            current_file['data'] = line
        else:
            current_file['data'] += line

境界に達するたびに、新しい「ファイル」辞書を開始することがわかります。私はヘッダーを解析していると言うように設定in_headerしました。True空白行に達したら、それを-に切り替えますが、そのフォーム値にが設定されているFalseかどうかを確認する前ではありません-そうでない場合は、ファイルのアップロードのみを探しているため、設定します。Content-Typeignore_current_file

ライブラリを使用する必要があることはわかっていますが、ドキュメントを読んだり、プロジェクトでさまざまなソリューションを機能させようとしたり、コードを合理的に見せたりすることにうんざりしています。この部分を乗り越えたいだけです。ファイルのアップロードを使用してHTTPPOSTを解析するのがこれほど簡単な場合は、それを使い続けます。

注:このコードは今のところ完全に機能します。特定のブラウザからのリクエストを抑制/吐き出すかどうか疑問に思っています。

4

3 に答える 3

7

この問題に対する私の解決策は、次のようなcgi.FieldStorageを使用してコンテンツを解析することでした。

class Root(Resource):

def render_POST(self, request):

    self.headers = request.getAllHeaders()
    # For the parsing part look at [PyMOTW by Doug Hellmann][1]
    img = cgi.FieldStorage(
        fp = request.content,
        headers = self.headers,
        environ = {'REQUEST_METHOD':'POST',
                 'CONTENT_TYPE': self.headers['content-type'],
                 }
    )

    print img["upl_file"].name, img["upl_file"].filename,
    print img["upl_file"].type, img["upl_file"].type
    out = open(img["upl_file"].filename, 'wb')
    out.write(img["upl_file"].value)
    out.close()
    request.redirect('/tests')
    return ''
于 2012-03-21T18:33:46.000 に答える
1

content-dispositionヘッダーにはフィールドの順序が定義されていません。さらに、ファイル名だけでなく、より多くのフィールドが含まれている場合があります。したがって、ファイル名の一致は失敗する可能性があります-ファイル名さえない可能性があります!

rfc2183を参照してください(メール用に編集してください。httpについてはrfc1806rfc2616などを参照してください)

また、この種の正規表現では、すべてのスペースを\ s *に置き換え、大文字と小文字を区別しないことをお勧めします。

于 2010-07-18T10:24:52.927 に答える
1

ドキュメントを読まないようにしていますが、実際に読むのが最善のアドバイスだと思います。

ケースを見逃さないように。より簡単な方法は、ポスターライブラリを使用することです。

于 2010-07-18T10:30:48.097 に答える