0

私はDjangoでこのような機能を持っています:

def uploaded_files(request):
    global source
    global password
    global destination
    username = request.user.username

        log_id = request.user.id
        b = File.objects.filter(users_id=log_id, flag='F')  # Get the user id from session .delete() to use delete
        source = 'sachet.adhikari@69.43.202.97:/home/sachet/my_files'
        password = 'password'
        destination = '/home/zurelsoft/my_files/'
        a = Host.objects.all() #Lists hosts
        command = subprocess.Popen(['sshpass', '-p', password, 'rsync', '--recursive', source],
                               stdout=subprocess.PIPE)
        command = command.communicate()[0]
        lines = (x.strip() for x in command.split('\n'))
        remote = [x.split(None, 4)[-1] for x in lines if x]
        base_name = [os.path.basename(ok) for ok in remote]
        files_in_server = base_name[1:]
        total_files = len(files_in_server)
        info = subprocess.Popen(['sshpass', '-p', password, 'rsync', source, '--dry-run'],
                               stdout=subprocess.PIPE)
        information = info.communicate()[0] 
        command = information.split()
        filesize = command[1] 
        #st = int(os.path.getsize(filesize))
        #filesize = size(filesize, system=alternative)
        date = command[2] 
        users_b = User.objects.all()
        return render_to_response('uploaded_files.html', {'files': b, 'username':username, 'host':a, 'files_server':files_in_server, 'file_size':filesize, 'date':date, 'total_files':total_files, 'list_users':users_b}, context_instance=RequestContext(request))  

この関数の主な用途は、ファイルをサーバーからローカル マシンに転送し、データをデータベースに書き込むことです。欲しいもの:コピーに時間がかかる10GBの単一ファイルがあります。コピーはコマンド ラインで rsync を使用して行われるため、ファイルの転送中にユーザーが他のメニューを操作できるようにしたいと考えています。どうすればそれを達成できますか?たとえば、ユーザーが [OK] を押すと、コマンド ラインでファイルが転送されるので、ユーザーに「ファイルが転送されています」というメッセージを表示し、カーソルのローリングなどを停止しますか? この場合、マルチプロセッシングまたはスレッド化は適切ですか? ありがとう

4

4 に答える 4

1

関数がビュー内で機能すると仮定すると、ブラウザは 10 GB のファイルの転送が完了する前にタイムアウトします。多分あなたはこれのためにあなたのアーキテクチャを再考する必要がありますか?

方法はいくつかあると思いますが、今思いついたのは以下の方法です。

1 つの解決策は、ファイル転送のステータスを保存する仲介者を持つことです。ファイルを転送するプロセスを開始する前に、プロセスが開始されたことを示すフラグをデータベースのような場所に設定します。次に、サブプロセスの呼び出しをブロックする場合は、それが完了するのを待ち、可能であればコマンドの出力を確認して、以前に設定したフラグを更新します。

次に、フロントエンドにファイル転送のステータスをポーリングさせます。

別の解決策として、例のようにサブプロセス呼び出しをノンブロッキングにする場合、その場合、そこに座っているスレッドを使用して、stdout を読み取り、フロントエンドが照会してより「リアルタイム」を取得できる中間ストアを更新する必要があります。転送プロセスの更新。

于 2013-01-24T10:42:08.323 に答える
1

必要なのはCeleryです。

並列タスクとしてジョブを生成し、http 応答を返すことができます。

于 2013-01-24T10:57:11.063 に答える
0

RaviU ソリューションは確実に機能します。

もう 1 つのオプションは、ブロッキング サブプロセスを独自のスレッドで呼び出すことです。このスレッドは、フラグまたは情報 (memcache、db、またはハードドライブ上のファイルのみ) の設定と、完了時のクリアを担当する可能性があります。個人的には、rsyncs stdout を読むことと私との間で愛が失われることはないので、通常は OS にファイルサイズを尋ねるだけです。

また、ファイルをできるだけ早く必要としない場合は、「-c」を追加してチェックサムを実行すると、それらの巨大なファイルに適しています。ソース: むらのあるキャンパス ネットワークを介して巨大なビデオ ファイルを転送しようとした個人的な経験。

これまでのすべてのソリューションの問題点は、「N」個のファイルでは機能しないことです。最終的に、各ファイルを一度に 1 回しか転送できないようにしても、多数の異なるファイルがある場合、最終的にはシステムが停止します。一度に 1 つのファイルだけになることがわかっている場合を除き、ある種のタスク キューを使用する方がよい場合があります。最近は使っていませんが、グーグルで簡単に検索したところ、悪くないように見えるセロリが見つかりました。

于 2013-01-24T11:09:58.103 に答える
0

すべての Web サーバーには、ファイルをアップロードする機能があります。また、大きなファイルに対して行うことは、ファイルをチャンクに分割し、チャンクを受信するたびにマージを行うことです。ここでできることは、値属性を持つ html ページに非表示のタグを含めることができ、その時点でアップロード Web サービスが OK メッセージを返すたびに、非表示の html 値を関連するものに変更し、書き込むこともできます。その非表示の html 要素の値を読み取り続け、ファイルのアップロードが終了したかどうかを確認する関数。

于 2013-01-24T11:14:17.020 に答える