如何让用户在文件生成时下载文件

时间:2018-11-30 20:48:17

标签: python http tcp server

我想让用户在尚未准备好文件时就开始下载它。我不想将用户发送到某个页面上说“等待30秒,正在准备文件”。我无法提前生成文件。我需要用户单击/发送表格,选择下载位置并开始下载。生成的文件将是zip,因此我想,应该可以发送带有前几个zip字节(始终相同)的文件名,并且在生成文件之前不要确认tcp数据包是否已正确发送或类似,然后在生成文件后发送其余的文件。

我该怎么做?是否有任何工具可以做到这一点。还是有更好的方法?更多高级解决方案更好,C不是我的强项。最好在Python中。谢谢。

正在生成的文件是zip,在尚未准备好之前,实际上还没有什么要发送的。基本上根据输入,我生成文件集(耗时数十秒),然后将其压缩并提供给用户。我的应用程序在Linux上的python中,但是我将使用的服务器并不重要。

3 个答案:

答案 0 :(得分:0)

在准备文件时,客户端很可能会超时(或等待30秒而不发出通知)。我在传输时会使用流压缩算法(gzip)来压缩文件。这不会导致最佳压缩,但是会以可预测的方式提供文件。

研究“ Content-Encoding:gzip” HTTP标头。

答案 1 :(得分:0)

通常,这样的应用程序将分两部分实现,例如票务系统。

  1. 当用户单击/提交表单时,该表单会将请求发送到服务,该服务将作为后台进程开始生成文件,然后(无需等待文件生成)它将生成票证/哈希代表新文件,然后将用户重定向到新URL,例如/files/<random-hash>

  2. 在此新URL /files/<random-hash>上,当文件尚未准备好时,它将返回一个简单的HTML页面,该页面向用户显示等待消息,并在该页面上保留一个脚本,每隔几秒钟刷新一次页面。只要文件尚未准备好,它就会一直显示此消息,但是一旦文件准备好,该URL就会在响应中返回实际文件内容,并带有适当的mime-header。

该解决方案使用数据库和一些编程即可轻松实现。但是,如果您正在寻找一种可以使用的现成工具,很抱歉,我对它不熟悉。希望有帮助。

答案 2 :(得分:0)

尽管声称这是不可能的,但我设法找到了一种方法。在此期间,我学到了一些Go语言,所以我用了,但是我想它与其他语言并没有太大区别。

基本上,第一个字节写入写入器,然后刷新。浏览器比等待休息。

package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "strings"
    "time"
)

func Zip(w http.ResponseWriter, r *http.Request) {
    file_name := r.URL.Path
    file_name = strings.TrimPrefix(file_name, "/files/")

    w.Header().Set("Content-type", "application/zip")
    w.Write([]byte{80})
    if f, ok := w.(http.Flusher); ok {
        f.Flush()
    }
    for {
        if _, err := os.Stat("./files/" + file_name); err == nil {
            fmt.Println("file found, breaking")
            break
        }
        time.Sleep(time.Second)
    }
    stream_file_bytes, err := ioutil.ReadFile("./files/" + file_name)
    if err != nil {
        fmt.Println(err)
        return
    }

    b := bytes.NewBuffer(stream_file_bytes)
    b.Next(1)
    b.WriteTo(w)
    fmt.Println("end")
}

func main() {
    http.HandleFunc("/files/", Zip)
    if err := http.ListenAndServe(":8090", nil); err != nil {
        panic(err)
    }
}