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 进行复制,因此我想让用户在传输文件时使用其他菜单。我怎样才能做到这一点?例如,如果用户按下确定,文件将在命令行中传输,所以我想向用户显示“文件正在传输”消息并停止滚动光标或类似的东西?在这种情况下,多处理或线程是否合适?谢谢

4

4 回答 4

1

你需要的是芹菜

它让您将作业作为并行任务生成并返回 http 响应。

于 2013-01-24T10:57:11.063 回答
1

假设该功能在视图内工作,您的浏览器将在 10GB 文件完成传输之前超时。也许您应该为此重新考虑您的架构?

可能有几种方法可以做到这一点,但现在我想到了一些方法:

一种解决方案是让中介存储文件传输的状态。在开始传输文件的过程之前,请在数据库之类的某处设置一个标志,表明该过程已经开始。然后,如果您使子进程调用阻塞,请等待它完成,如果可能,检查命令的输出并更新您之前设置的标志。

然后让任何前端轮询文件传输的状态。

另一种解决方案,如果您像示例中那样使子进程调用非阻塞,在这种情况下,您应该使用位于那里的线程读取标准输出并更新您的前端可以查询的中间存储以获得更“实时”更新传输过程。

于 2013-01-24T10:42:08.323 回答
0

RaviU 解决方案肯定会奏效。

另一种选择是在自己的线程中调用阻塞子进程。该线程可能负责设置标志或信息(在 memcache、db 或只是硬盘驱动器上的文件中)以及在完成时清除它。就个人而言,阅读 rsyncs stdout 和我之间并没有失去爱,所以我通常只向操作系统询问文件大小。

此外,如果您绝对不需要该文件,则添加“-c”来执行校验和对于那些巨大的文件可能会有好处。资料来源:尝试通过参差不齐的校园网络传输巨型视频文件的个人经验。

我会说到目前为止所有解决方案的一个问题是它不适用于“N”个文件。最终,即使您确保每个文件一次只能传输一次,但如果您有很多不同的文件,那么最终它会使系统陷入困境。除非您知道它一次只能是一个文件,否则您最好只使用某种任务队列。我最近没用过,但是快速谷歌搜索产生了芹菜,看起来不错。

于 2013-01-24T11:09:58.103 回答
0

每个 Web 服务器都有上传文件的功能。它对大文件的作用是将文件分成块,并在收到每个块后进行合并。你可以在这里做的是,你可以在你的 html 页面中有一个隐藏的标签,它有一个 value 属性,每当你的上传网络服务在那个时间点向你返回一个 ok 消息时,你可以将隐藏的 html 值更改为相关的东西,也可以写一个持续读取该隐藏 html 元素的值并检查您的文件上传是否已完成的函数。

于 2013-01-24T11:14:17.020 回答