2017-02-28 83 views
1

我的問題/挑戰非常類似於幾個不同的Stack Overflow帖子,但我詳細閱讀了它們,仍然努力爭取即使是最基本的應用程序工作。具體來說,我相信"Returning binary file from controller in ASP.NET Web API""How to return a file (FileContentResult) in ASP.NET WebAPI"都非常接近我想要實現的目標。試圖編寫Web服務器端文件通過C#下載文件內容的主體是文件內容

爲了給你提供上下文,我試圖寫一個/存根一個簡單的固件OTA(無線)服務器。我最初的目標看似非常簡單,但我花了很多時間幾乎沒有進步。我想提供一個可以從瀏覽器(最終在物聯網設備上運行一些固件)中獲取的URL,它將接受一些參數(通過URL參數或通過標題)。如果固件更新可用,則調用應該返回一個文件作爲響應的主體,或者如果當前沒有更新,則返回適當的HTTP響應代碼(或者僅僅是空的消息體)。

我對Visual Studio for Website應用程序並不是非常有經驗,但是在C#中有很多的舒適,並且它似乎是一個很好的運行環境。我接受其他實現,但我認爲編寫控制器是最簡單的方法。我在瞭解到,這個Web API主要用於.Net和.Net通信,所以如果有更好的平臺,我很樂意指出一個更好的方向。這是我放在一起(以上巨資利用環節,所以沒有信用應付給我!):

namespace OverTheAirApi.Controllers 
{ 
[Route("api/[controller]")] 
public class OTAController : ApiController 
{ 
    [HttpGet] 
    public HttpResponseMessage Download(string name) 
    { 
     string fileName = "hello-world.bin"; 
     string filePath = "C:\\Devel\\Code\\...\\hello_world\\build\\" + fileName; 

     HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); 
     var stream = new FileStream(filePath, FileMode.Open); 
     result.Content = new StreamContent(stream); 
     result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment"); 
     result.Content.Headers.ContentDisposition.FileName = Path.GetFileName(filePath); 
     result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 
     result.Content.Headers.ContentLength = stream.Length; 
     return result; 

    } 
} 

}

當我在URL http://localhost:2265/api/ota型,我在屏幕上看到下面的原始輸出:

{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},"content":{"headers":[{"key":"Content-Disposition","value":["attachment; filename=hello-world.bin"]},{"key":"Content-Type","value":["application/octet-stream"]},{"key":"Content-Length","value":["407904"]}]},"statusCode":200,"reasonPhrase":"OK","headers":[],"requestMessage":null,"isSuccessStatusCode":true} 

整個響應,在Fiddler2捕獲看起來像這樣:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel
X-SourceFiles: =?UTF-8?B? YzpcdXNlcnNcZG91Z2NcZG9jdW1lbnRzXHZpc3VhbCBzdHVkaW8gMjAxNVxQcm9qZWN0c1xPdmVyVGhl QWlyQXBpXHNyY1xPdmVyVGhlQWlyQXBpXGFwaVxvdGE=?=
X-Powered-By: ASP.NET
Date: Tue, 28 Feb 2017 16:43:01 GMT
192
{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},"content":{"headers":[{"key":"Content-Disposition","value":["attachment; filename=hello-world.bin"]},{"key":"Content-Type","value":["application/octet-stream"]},{"key":"Content-Length","value":["407904"]}]},"statusCode":200,"reasonPhrase":"OK","headers":[],"requestMessage":null,"isSuccessStatusCode":true}
0

(很抱歉,如果該格式是有點難看,我想我需要使用MD一些輔導FO r HTTP響應也是如此!)

再一次,我的目標是編寫C#代碼,它將返回一個HTTP響應,其中標題指示該文件是附件,並且消息的主體只是文件本身。

再次感謝您提供任何幫助/見解!

謝謝你 - 道格。

+0

只是爲了說明問題,我面對的問題與我創建項目的方式有關。我通過混合使用ASP.Net Web API 2和ASP.Net Core引用和程序集來創建我的VS項目。使用[本指南]構建的乾淨項目(https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your -first-web-api),我能夠讓這段代碼正常工作。謝謝@ ron -c的幫助! –

+0

更多詳細信息...如果您創建一個ASP.Net Core 1.0.1項目,這不起作用。相反,它將返回XML,如上所述。最後,我的問題的解決方案是創建一個ASP.NET Web API 2項目,而不是使用ASP.NET Core ... –

回答

1

這是我發送文件到瀏覽器的標準方法。該方法有兩個參數,一個是文件的內容,另一個是客戶端將收到的默認文件名。請享用。

/// <summary> 
    /// Sends the fileData to the browser and prompts the visitor to save it with the 
    /// name specified in fileName. 
    /// </summary> 
    /// <param name="defaultFilename">File name to use when browser prompts visitor (spaces will be replaced with dashes)</param> 
    /// <param name="data">Data to be sent to visitor's browser</param> 
    /// <param name="errorMsg"></param> 
    // Mod 08/04/09 Ron C - Reworked code to work right in modern browsers. 
    public static bool DownloadToBrowser(string data, string defaultFilename, out string errorMsg){ 
     errorMsg = ""; 
     System.Web.HttpResponse response = HttpContext.Current.Response; 

     try { 
      defaultFilename = defaultFilename.Replace(' ', '-');  //firefox will cut the name off at the space if there is one, so get rid of 'em 
      response.Clear(); 
      response.ContentType = "application/octet-stream"; 
      response.AddHeader("Content-Disposition", "attachment; filename=" + defaultFilename); 
      //8/5/09 Adding a "Content-Length" header was cutting off part of my file. Apparently 
      //  it would need to factor in the length of the headers as well as the conent. 
      //  since I have no easy way to figure out the length of the headers, initially I was gonna 
      //  eliminate "Content-Length" header. Doing so works great in IE 7 and FireFox 3, but not 
      //  in Safari 3 or 4(which doesn't download the file without the "Content-Length" header. So I 
      //  resorted to a cludge of using the header tag and setting it to content length + 1000 for headers. 
      //  I'd love to have a better solution, but his one works and I've already wasted 6+ hours to get to this 
      //  solution. Cross broswer downloading of a file shouldn't have to be so hard. -Ron 
      int len = data.Length + 1000; 
      response.AddHeader("Content-Length", len.ToString()); //file size for progress dialog 
      response.Write(data); 
      response.Flush(); 
      response.Close();  //Close() needed to prevent html from page being streamed back after the file data we sent. 

      //Don't use response.End() cause it throws a thread abort exception that can't be caught! Actually you can 
      //catch it but then it rethrows after the catch block! (What bozo thought that up?). I found lots of threads on this. 


     } catch (Exception ex) { 
      errorMsg = "Unable to download file to browser."; 
      //Add code here to log the error in your environment 
      return false; 
     } 
     return true; 
    } 
+0

Ron先生 - 感謝您的迴應。我感謝幫助!你是否建議我將此與上面實現的Web Api調用結合使用?如果不是,應該如何連接到HTTP GET命令?我問的原因是因爲我最初嘗試使用你的代碼在兩個方面是失敗的。一個是我不確定從Web Api命令返回什麼,另一個是System.Web.HttpContext.Current被設置爲null。任何額外的幫助將不勝感激!感謝YOu,祝你有美好的一天! –

+0

我通過調用這個方法並傳遞參數,從web窗體.aspx頁面使用這段代碼。但是,它也應該從Web API端點起作用,在從您的操作方法調用此方法之後,您只需返回一個狀態代碼200並且不需要額外的內容。 –