【问题标题】:How to check if a file download is complete in Web API如何在 Web API 中检查文件下载是否完成
【发布时间】:2015-09-28 21:15:58
【问题描述】:

我正在执行一项任务,用户可以下载 excel 格式的数据。 数据是动态生成的(作为通用列表),然后写成excel文件,效果很好。

问题:

我面临的问题是,当数据很大时,下载文件需要几秒钟。在此期间,我需要向最终用户显示某种进度/指示(比如说,正在下载....消息)。使用当前代码,我无法跟踪文件下载完成的时间......

这是我的代码

通过 web api 方法和搜索条件的 JS 代码

var request = {};
request.Code = codeDdl.find(':selected').val();

$.blockUI({ message: '<h3>Downloading...</h3>' });
//Export to Excel all records
$().largeDownload("api/FileDownload/GetWorkQueueList", {
   'request': JSON.stringify(request)
});

读取搜索条件并将其传递给 web api 方法的 JS 代码:

(function (d) {
    d.fn.largeDownload = function (a, b, c) { void 0 !== c ? (c = c.toUpperCase(), "GET" != c && (c = "POST")) : c = "POST"; if (void 0 === b || !1 == b) b = d().parse_url(a), a = b.url, b = b.params; var e = d("<form></form"); e.attr("method", c); e.attr("action", a); for (var f in b) a = d("<input />"), a.attr("type", "hidden"), a.attr("name", f), a.attr("value", b[f]), a.appendTo(e); d("body").append(e); e.bind("submit", DownloadedCallback); e.submit() }; d.fn.parse_url = function (a) {
        if (-1 == a.indexOf("?")) return { url: a, params: {} }; var b = a.split("?"), a = b[0], c = {}, b = b[1].split("&"), e = {}, d; for (d in b) {
            var g =
            b[d].split("="); e[g[0]] = g[1]
        } c.url = a; c.params = e; return c
    }
})(jQuery);

Web API

    [HttpPost]
    public HttpResponseMessage GetWorkQueueList()
    {
        var resp = new HttpResponseMessage(HttpStatusCode.OK);
        var currentContext = HttpContext.Current;

        try
        {
            string strRequest = currentContext.Request.Form["request"];
            var serializer = new JavaScriptSerializer();
            var request = serializer.Deserialize<ViewRequest>(strRequest);
            request.QueryAllRecords = true;
            var workQueueList = MappingManager.GetWorkQueueList(request);

            var legacyExcelView = //get data as generic list
            ....
            ....

            var fileBytes = ExcelManager.GetExcelData<WQExcelView>(legacyExcelView);
            var stream = new MemoryStream(fileBytes);
            resp.Content = new StreamContent(stream);
            resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            resp.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "WorkQueueList.xlsx" };
            resp.Content.Headers.Add("Content-Encoding", "UTF-8");
            return resp;
        }
        catch (Exception ex)
        {                
            resp.Content = new StringContent(ex.Message);
            return resp;
        }
    }

我的尝试:

在 largeDownload javascript 函数中,我添加了 DownloadedCallback,它似乎不像我预期的那样工作。它会在下载完成之前立即触发。

问题:

如何在 Web API 方法中检查文件下载是否完成...在显示文件下载对话框之前我应该​​怎么做才能显示进度条?

【问题讨论】:

    标签: javascript jquery asp.net-web-api export-to-excel


    【解决方案1】:

    我们通常通过 2-3 次 API 调用来解决问题。我们的应用程序是用 Java 编写的;但是,这里也适用相同的基本原则。

    第一个调用是在单独的线程中启动大型 SQL 查询、大型文件创建等。该请求会立即返回,有时会带有一个 id 来引用原始请求。

    在生成的线程中写入 CSV 中的行时,我们在原始线程中写入两个属性值,用于处理的行数和总行数。如果它是一个大型 SQL 语句,我们经常将语句本身批处理成几个有限的 SQL 语句,以便可以增量设置和显示进度值,而不是在 0% 上停留一段时间然后快速调整到 100%。拆分 SQL 语句通常只会增加几毫秒的成本,但会在用户体验方面提供大量价值。

    我们有第二个 API 调用被轮询,然后返回处理的数量和总计数的属性值。这就是我们用来为进度条设置动画的东西。当达到 100% 或该调用响应的状态标志发生变化时,我们通常会在单独的 API 调用中请求完成的文件。您还可以在同一个进度调用中返回文件指针/路径。

    【讨论】:

    • 感谢您提供一些指导。我不确定我是否能够打破sql语句......我的sql语句非常复杂(连接了几个表)并且带来了很多数据。
    • 可以理解。您可能想要分析现在大部分时间都花在了哪里。通常,大部分时间都花在 SQL 调用上。您不必对查询进行太多修改 - 您可以指定一个限制,然后每次增加起始索引或偏移量以请求下一组行(像您一样设置进度属性)。
    • 另外,看起来你正在使用 jQuery——看看延迟对象:api.jquery.com/category/deferred-object。您可以将所有初始请求和进度请求包含在一个类中,并在您有进度更新和文件完成时通知调用者。
    • 好的,我会看看延迟对象。
    猜你喜欢
    • 2019-09-15
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多