2015-07-10 72 views
3

我正在處理用戶可以以excel格式下載數據的任務。 數據是動態生成的(作爲通用列表),然後寫入excel文件,這是完美的工作。如何檢查Web API中的文件下載是否已完成

問題:

我現在面臨的問題是,當數據是巨大的,它需要幾秒鐘下載的文件。在此期間,我需要向最終用戶展示某種進步/跡象(比方說,下載....消息)。在當前的代碼,我不能夠跟蹤文件下載完成後...

這裏是我的代碼

其通過JS代碼的Web API方法和搜索條件

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) 
}); 

JS代碼讀取搜索標準,並將它傳遞到網絡API方法:

(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方法完成......我應該怎麼做,以顯示進度條,直到顯示文件下載對話框?

回答

0

我們通常用2-3個API調用來解決問題。我們的應用程序是用Java編寫的;然而,這裏適用相同的基本原則。

第一個調用是在單獨的線程中啓動大型SQL查詢,大型文件創建等。該請求立即返回,有時用id來引用原始請求。

雖然CSV中的行正在寫入產生的線程,但我們在原始線程中爲處理的行數和總行寫入了兩個屬性值。如果它是一個大SQL語句,我們通常會將語句本身批量處理爲幾個有限的SQL語句,以便可以逐步設置和顯示進度值,而不是一時坐在0%,然後達到100%。分解SQL語句通常只需要幾毫秒的額外成本,但在用戶體驗方面卻提供了大量價值。

我們有第二個API調用被輪詢,然後返回處理的數量和總數的屬性值。這是我們用來激活我們的進度條的動畫。當該命令的響應改變達到100%或狀態標誌發生變化時,我們通常會在單獨的API調用中請求完成的文件。您也可以在同一個進度調用中返回文件指針/路徑。

+0

感謝您提供一些指導。我不確定我是否能夠打破sql語句......我的sql語句非常複雜(連接多個表)並帶來大量數據。 –

+0

可以理解。你可能想要知道大部分時間都在哪裏。通常,大部分時間都花在SQL調用上。您不必非常多地修改查詢 - 您將指定一個限制,然後每次增加起始索引或偏移量以請求下一組行(設置您的進度屬性)。 –

+1

此外,它看起來像你使用jQuery - 看看延期對象:https://api.jquery.com/category/deferred-object/。您可以在一個類中包含所有初始和進度請求,並在進度更新和文件完成時通知調用者。 –