2015-05-12 53 views
9

如何獲得我使用WebClient從WebAPI控制器返回的內容處置參數?獲取內容處置參數

的WebAPI控制器

[Route("api/mycontroller/GetFile/{fileId}")] 
    public HttpResponseMessage GetFile(int fileId) 
    { 
     try 
     { 
       var file = GetSomeFile(fileId) 

       HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); 
       response.Content = new StreamContent(new MemoryStream(file)); 
       response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); 
       response.Content.Headers.ContentDisposition.FileName = file.FileOriginalName; 

       /********* Parameter *************/ 
       response.Content.Headers.ContentDisposition.Parameters.Add(new NameValueHeaderValue("MyParameter", "MyValue")); 

       return response; 

     } 
     catch(Exception ex) 
     { 
      return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex); 
     } 

    } 

客戶

void DownloadFile() 
    { 
     WebClient wc = new WebClient(); 
     wc.DownloadDataCompleted += wc_DownloadDataCompleted; 
     wc.DownloadDataAsync(new Uri("api/mycontroller/GetFile/18")); 
    } 

    void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) 
    { 
     WebClient wc=sender as WebClient; 

     // Try to extract the filename from the Content-Disposition header 
     if (!String.IsNullOrEmpty(wc.ResponseHeaders["Content-Disposition"])) 
     { 
      string fileName = wc.ResponseHeaders["Content-Disposition"].Substring(wc.ResponseHeaders["Content-Disposition"].IndexOf("filename=") + 10).Replace("\"", ""); //FileName ok 

     /****** How do I get "MyParameter"? **********/ 

     } 
     var data = e.Result; //File OK 
    } 

我要回的的WebAPI控制器文件,我在響應內容報頭附加文件名,而且我想返回一個附加價值。

在客戶端我能夠獲得文件名,但我如何獲得aditional參數?

回答

15

如果您正在使用.NET 4.5或更高版本的工作,可以考慮使用System.Net.Mime.ContentDisposition類:

string cpString = wc.ResponseHeaders["Content-Disposition"]; 
ContentDisposition contentDisposition = new ContentDisposition(cpString); 
string filename = contentDisposition.FileName; 
StringDictionary parameters = contentDisposition.Parameters; 
// You have got parameters now 

編輯:

否則,你需要分析根據它的Content-Disposition頭specification

下面是一個簡單的類進行解析,貼近規格:

static void Main() {   
    string text = "attachment; filename=\"fname.ext\"; param1=\"A\"; param2=\"A\";"; 

    var cp = new ContentDisposition(text);  
    Console.WriteLine("FileName:" + cp.FileName);   
    foreach (DictionaryEntry param in cp.Parameters) { 
     Console.WriteLine("{0} = {1}", param.Key, param.Value); 
    }   
} 
// Output: 
// FileName:"fname.ext" 
// param1 = "A" 
// param2 = "A" 

認爲,應考慮的唯一事情:

class ContentDisposition { 
    private static readonly Regex regex = new Regex("^([^;]+);(?:\\s*([^=]+)=(\"[^\"]*\");?)*$", RegexOptions.Compiled); 

    private string fileName; 
    private StringDictionary parameters; 
    private string type; 

    public ContentDisposition(string s) { 
     if (string.IsNullOrEmpty(s)) { 
      throw new ArgumentNullException("s"); 
     } 
     Match match = regex.Match(s); 
     if (!match.Success) { 
      throw new FormatException("input is not a valid content-disposition string."); 
     } 
     var typeGroup = match.Groups[1]; 
     var nameGroup = match.Groups[2]; 
     var valueGroup = match.Groups[3]; 

     int groupCount = match.Groups.Count; 
     int paramCount = nameGroup.Captures.Count; 

     this.type = typeGroup.Value; 
     this.parameters = new StringDictionary(); 

     for (int i = 0; i < paramCount; i++) { 
      string name = nameGroup.Captures[i].Value; 
      string value = valueGroup.Captures[i].Value; 

      if (name.Equals("filename", StringComparison.InvariantCultureIgnoreCase)) { 
       this.fileName = value; 
      } 
      else { 
       this.parameters.Add(name, value); 
      } 
     } 
    } 
    public string FileName { 
     get { 
      return this.fileName; 
     } 
    } 
    public StringDictionary Parameters { 
     get { 
      return this.parameters; 
     } 
    } 
    public string Type { 
     get { 
      return this.type; 
     } 
    } 
} 

然後你就可以以這種方式使用它使用這個類是它不處理參數(或文件名)沒有雙引號。

+0

太棒了,我會將它標記爲正確答案,您是否從頭開始編寫該類?如果沒有,請說明來源。 – Tuco

+0

是的,我做過了,但正如我所提到的,它可能需要進一步改進,但我希望它能解決您的問題。 –

1

值是在那裏我只需要提取它:

的Content-Disposition頭返回這樣的:

Content-Disposition = attachment; filename="C:\team.jpg"; MyParameter=MyValue 

所以我只是用一些字符串操作得到的值:

void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) 
{ 
    WebClient wc=sender as WebClient; 

    // Try to extract the filename from the Content-Disposition header 
    if (!String.IsNullOrEmpty(wc.ResponseHeaders["Content-Disposition"])) 
    { 
     string[] values = wc.ResponseHeaders["Content-Disposition"].Split(';'); 
     string fileName = values.Single(v => v.Contains("filename")) 
           .Replace("filename=","") 
           .Replace("\"",""); 

     /********** HERE IS THE PARAMETER ********/ 
     string myParameter = values.Single(v => v.Contains("MyParameter")) 
            .Replace("MyParameter=", "") 
            .Replace("\"", ""); 

    } 
    var data = e.Result; //File ok 
} 
+0

看起來不錯,我只是添加一個修剪()。由於解析該類中的錯誤,我無法使用System.New.Mime.ContentDisposition。 –

4

您可以使用以下框架代碼解析出內容配置:

var content = "attachment; filename=myfile.csv"; 
var disposition = ContentDispositionHeaderValue.Parse(content); 

然後就拿掉配置實例的部分。

disposition.FileName 
disposition.DispositionType