2

私は最近、とても良いと思う Web2py フレームワークに飛び込みました。しかし、私は今、「基本的な」問題で立ち往生しています。

環境

私が構築している Web サイトは、科学コードのインターフェイスです。人々はフォームに入力して送信します。データ (共有フォルダー内のファイルに書き込まれる) は、コードによって処理され、バックグラウンドでデーモンとして実行されます (この共有フォルダーと 間の JSONRPC リンクを除いて、コードには Web サイトとのリンクはありませんcode->website)。このコードは、Web サイトのユーザーが利用できるようにしたいファイルと画像を生成します (つまり、ユーザーが要求した結果を返します)。ジョブが完了すると、コードは完全に機能する JSONRPC サービス リンクを使用して結果を Web サイトに「プッシュ」します。結果は、基本的に次の構造を持つ生成された名前のフォルダーにあります。

unique_folder_name/
        file1.txt
        file2.csv
        file3.xls
        image1.png
        image2.png

現在の実装 (正しく動作していません)

現在、私は3つのDBを持っています:

# Job database
db.define_table("job",
    Field('owner', 'string', length=60, required=True, writable=True, readable=True),
    Field('uniq_id', "string", length=60, required=True, unique=True, writable=False, readable=True))

# Result database
db.define_table("result",
    Field("job", "reference job"),
    Field("x", "integer", default=1),
    Field("y", "integer", default=0),
    Field("z", "integer", default=0),
    Field("data", "string", length=500),
    Field("message", "string", length=200))

# File database
db.define_table("file",
    Field("job", "reference job"),
    Field("file", "upload"),
    Field("isimage", "boolean", default=False))

コードが結果を「プッシュ」すると、Web2py の一部のモジュールが「結果」データベースにエントリを作成し、ジョブに関連付けられた「ファイル」データベースにエントリを作成します。アップロード フォルダーにコピーせずにファイル (既にファイル システムにある) を Web2py で使用できるようにする方法が見つからなかったため、現在、そのようなファイルを (モジュールに) 保存しています。

stream = open(os.path.join(directory, _file), 'rb')
current.db.file.insert(job=jid, file=current.db.file.file.store(stream, _file), isimage=isimg)

次に、画像を使用してビューを作成する場合は、(モジュール内で) 次のようにします。

rows = current.db((current.db.file.job==jid) & (current.db.file.isimage==True)).select()
for row in rows:
    div.append(I(_src=URL(c="default", f="download", args=os.path.join(directory, row.file)), _width="500", _height="500"))

およびビュー内: `{{=div}}`

問題

これは機能していません...表示されたページのソースコードは次のようになります。

<i height="500" src="/mycode/default/download//path/to/directory/file.file.9b7d3a0367de0843.6d732d72732e706e67.png" width="500"></i>

この URL をアドレス バーに入力すると、ファイルは正しくダウンロードされますが、それ以外の場合、画像は Web ページに表示されません。また、Web2py がファイルを 'upload' フォルダー (新しい安全な醜い名前で:)) にコピーしたとしても、ファイルのパスを指定する必要があります。そうしないと、リンクが機能しません。したがって、画像は表示されず、ファイルはとにかく「アップロード」フォルダーにコピーされます:(

私は迷っており、これを修正する方法がわかりません。(画像の URL を作成するときにリクエスト オブジェクトを追加しようとしましたが、カスタム ダウンロード機能も試しましたが、これまでのところ機能していません)。

編集(解決策)

さて、私が見逃していた私のコードには明らかなバグがあります: images tag helper is not I, しかしIMG:) アイコンの Twitter ブートストラップで使用されるタグとの混乱から生じる単純な間違いI...それで表示の問題は解決します。アップロード フォルダーにファイルをコピーせずにファイルをストリーミングする (つまりupload、DB のフィールドを使用しない) ために、rochacbruno (彼に感謝します) は私を正しい軌道に乗せました。完全な解決策については、私自身の回答を参照してください。

4

3 に答える 3

2

だからここに私の問題に対する完全な解決策があります。

ファイルではdb.py、「ファイル」テーブルを次の定義に置き換えました (そのため、ファイルはそのままの場所に留まり、web2py アップロード フォルダーにはコピーされません)。

# File database
db.define_table("file",
    Field("job", "reference job"),
    Field("name", "string", length=30, required=True),   # stores the filename (without path)
    Field("isimage", "boolean", default=False))

次に、コントローラー (「mycontroller」など) で、ファイルをストリーミングするためにこの関数を定義しました。

from mymodule import OUTPUT  # this is the base directory of the files
from gluon.contenttype import contenttype

def export():
    # allow to download files
    jid = request.args(0)
    fid = request.args(1)

    if None in (jid, fid):
        res = 'Invalid URL'
    else:
        # get the file row
        row = db.file(fid)

        # some checks (not necessary if you know what you're doing)
        jrow = db.job(jid)
        if row is None:
            res = "unknown file ID"
        elif jrow.id  is None:
            res = "unknown job ID"
        else:
            filename = row.name
            # jrow.perma_id, is a field in the 'job' DB, that I use to create a unique
            # directory name, so the files of job ID 'jid' are under: OUTPUT/perma_id/
            fullname = os.path.join(OUTPUT, jrow.perma_id, filename)

            ext = os.path.splitext(filename)[1]
            response.headers['Content-Type'] = contenttype(ext)
            response.headers['Content-disposition'] = 'attachment; filename=%s' % filename
            res = response.stream(open(fullname, "rb"), chunk_size=4096)

    return res

この時点で別の問題に遭遇したことに注意してください。最初はフルパスをリクエスト引数として渡すことを考えていましたが(例:)、多くの引数に分割された「/」が含まれURL(c='mycontroller', f='export', args=(path, filename))ていたため、機能しませんでした..path私のように簡単なパスがない場合 (つまり、コンポーネントを 1 つ変更するだけ)、パスをたとえば「ファイル」DB に保存できます。

次に、ビューの場合(モジュールまたは好きなものを使用):

rows = current.db((current.db.file.job==jid) & (current.db.file.isimage==True)).select()
for row in rows:
    div.append(IMG(_src=URL(c="mycontroller", f="export", args=(jid, fid), _width="500", _height="500"))

Iヘルパー タグが正しいタグに置き換えられていることに注意してくださいIMG。「jid」はジョブID、「fid」は表示・ダウンロードしたいファイルIDです。

于 2012-09-22T19:09:45.137 に答える
1

独自のダウンロード関数を作成する必要があります

import os
def my_download():
    base_path = request.args(0) # /path
    subdirectory = request.args(1) # directory
    filename = request.args(2)
    fullpath = os.path.join(request.folder, base_path, subdirectory, filename)
    response.stream(os.path.join(request.folder, fullpath))

default/download は、db およびデフォルトの保存方法で使用することを目的としています。

于 2012-09-22T04:27:58.900 に答える