2015-05-12 19 views
9

Làm cách nào để lấy các tham số Nội dung-Bố trí mà tôi đã trả về từ bộ điều khiển WebAPI bằng WebClient?Lấy tham số Nội dung-Bố trí

khiển 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); 
     } 

    } 

Khách hàng

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 
    } 

Tôi đang trở về một tập tin từ bộ điều khiển WebAPI, tôi gắn tên tập tin trong tiêu đề nội dung trả lời, nhưng tôi cũng muốn để trả về giá trị quảng cáo.

Trong ứng dụng khách, tôi có thể lấy tên tệp, nhưng làm cách nào để nhận thông số quảng cáo?

Trả lời

15

Nếu bạn đang làm việc với .NET 4.5 hoặc mới hơn, xem xét sử dụng lớp 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 

Edit:

nếu không, bạn cần phải phân tích header Content-Disposition theo nó specification.

Đây là một lớp đơn giản mà thực hiện việc phân tích, gần với đặc điểm kỹ thuật:

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

Sau đó, bạn có thể sử dụng nó theo cách này:

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" 

Điều duy nhất cần được xem xét khi sử dụng lớp này là nó không xử lý các tham số (hoặc tên tệp) mà không có một báo giá kép.

+0

Tuyệt vời, tôi sẽ đánh dấu đó là câu trả lời đúng, bạn đã viết lớp từ đầu chưa? nếu không, vui lòng cho biết nguồn. – Tuco

+0

Vâng tôi đã làm, nhưng như tôi đã đề cập, nó có thể cần cải tiến hơn nữa, nhưng tôi hy vọng nó giải quyết vấn đề của bạn. –

1

Giá trị là ở đó tôi chỉ cần giải nén nó:

Phần header Content-Disposition được trả lại như thế này:

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

Vì vậy, tôi chỉ sử dụng một số thao tác chuỗi để có được các giá trị:

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

Có vẻ tốt, tôi chỉ cần thêm một Trim(). Tôi không thể sử dụng System.New.Mime.ContentDisposition do lỗi phân tích cú pháp trong lớp đó. –

4

Bạn có thể phân tích cách bố trí nội dung bằng cách sử dụng mã khuôn khổ sau:

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

Sau đó, chỉ cần lấy các phần ra khỏi thể hiện bố trí.

disposition.FileName 
disposition.DispositionType 
Các vấn đề liên quan