使用http.Redirect和multipart请求获取连接重置错误

时间:2017-01-29 12:59:11

标签: http go

这是我的经纪人:

func VideosStoreHandler(w http.ResponseWriter, r *http.Request) {
    r.ParseMultipartForm(32 << 20)

    clientFile, header, err := r.FormFile("file")
    if err != nil {
        logs.Create(logs.LevelError, "[VideosStoreHandler] Unable to parse uploaded file: "+err.Error())
        return
    }
    defer clientFile.Close()

    tfn := fmt.Sprintf("%s%d%s", config.TmpDir, time.Now().UnixNano(), filepath.Ext(header.Filename))
    tmpFile, err := os.OpenFile(tfn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
    if err != nil {
        logs.Create(logs.LevelError, "[VideosStoreHandler] Unable to create temporary file: "+err.Error())
        return
    }
    defer tmpFile.Close()

    io.Copy(tmpFile, clientFile)

    msg := fmt.Sprintf("[VideosStoreHandler] Video %q uploaded with filename: %q.", r.FormValue("name"), header.Filename)
    logs.Create(logs.LevelInfo, msg)

    vid := videos.CreateVideo(r.FormValue("name"), filepath.Ext(header.Filename))

    go util.ParseVideo(vid, r.FormValue("name"), tmpFile.Name())

    http.Redirect(w, r, "/admin/logs", http.StatusTemporaryRedirect)
}

ParseVideo功能:

func ParseVideo(vid int64, vname, fname string) {
    defer os.Remove(fname)

    file, err := os.Open(fname)
    if err != nil {
        logs.Create(logs.LevelError, "[ParseVideo] Unable to open temporary file: "+err.Error())
        return
    }
    defer file.Close()

    fstat, err := file.Stat()
    if err != nil {
        logs.Create(logs.LevelError, "[ParseVideo] Unable to get file info: "+err.Error())
        return
    }

    fileSize := fstat.Size()
    totalPartsNum := uint64(math.Ceil(float64(fileSize) / float64(config.ChunkSize)))

    prefix := fmt.Sprintf("%d", time.Now().UnixNano())

    time.Sleep(5 * time.Second) // NOTE: This is intentional, for testing.

    for i := uint64(0); i < totalPartsNum; i++ {
        time.Sleep(5 * time.Second) // NOTE: This is intentional, for testing.

        partSize := int(math.Min(config.ChunkSize, float64(fileSize-int64(i*config.ChunkSize))))
        partBuffer := make([]byte, partSize)

        file.Read(partBuffer)
        encrypted, err := crypt.EncryptChunk(partBuffer)
        if err != nil {
            logs.Create(logs.LevelError, "[ParseVideo] Failed to encrypt chunk file: "+err.Error())
            return
        }

        fileName := fmt.Sprintf("%s%s%d", config.ChunksDir, prefix, i)
        chunkFile, err := os.Create(fileName)
        if err != nil {
            logs.Create(logs.LevelError, "[ParseVideo] Unable to create chunk file: "+err.Error())
            return
        }
        chunkFile.Close()

        err = ioutil.WriteFile(fileName, encrypted, os.ModeAppend)
        if err != nil {
            logs.Create(logs.LevelError, "[ParseVideo] Writing to chunk file failed: "+err.Error())
            return
        }

        videos.CreateChunk(vid, fileName)

        msg := fmt.Sprintf("[ParseVideo] Chunk %d of %q stored in %q.",
            i, vname, fileName)
        logs.Create(logs.LevelInfo, msg)
    }

    msg := fmt.Sprintf("[ParseVideo] %q processing finished without errors.", vname)
    logs.Create(logs.LevelSuccess, msg)
}
提供LogsHandler

/admin/logs

func LogsHandler(w http.ResponseWriter, r *http.Request) {
    data := struct {
        Items []logs.Log
    }{}

    rows, err := logs.FetchAll()
    if err != nil {
        logs.Create(logs.LevelError, "[LogsHandler] Failed to fetch logs: "+err.Error())
        return
    }

    for rows.Next() {
        var item logs.Log

        if err := rows.Scan(&item.Level, &item.Message, &item.Timestamp); err != nil {
            logs.Create(logs.LevelError, "[LogsHandler] Failed to scan log items: "+err.Error())
            return
        }

        data.Items = append(data.Items, item)
    }

    if err := rows.Err(); err != nil {
        logs.Create(logs.LevelError, "[LogsHandler] SQL Error: "+err.Error())
        return
    }

    template.Render("admin/logs.html", data, w)
}

Render功能:

func Render(filePath string, data interface{}, w http.ResponseWriter) {
    fp := path.Join("templates", filePath)
    tmpl, err := template.ParseFiles(fp, "templates/layouts/master.html")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    if err := tmpl.Execute(w, data); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

我想在日志中显示解析进度。日志工作正常,但http.Redirect不起作用(我在其他处理程序中使用此方法,我需要重定向,它们工作正常),我的浏览器显示此错误: enter image description here

通过Chrome开发人员工具检查响应,网络选项卡中没有响应。通过手动浏览到/admin/logs,它加载就好了!

问题出在哪里?

0 个答案:

没有答案