2010-04-15 20 views
6

में प्रतिरूपण मेरे पास एक ऐसी क्रिया है जिसे सुरक्षित स्थान से फ़ाइल को पढ़ने की आवश्यकता है, इसलिए मुझे फ़ाइल को पढ़ने के लिए प्रतिरूपण का उपयोग करना होगा।एएसपी.नेट एमवीसी

इस कोड काम करता है:

[AcceptVerbs(HttpVerbs.Get)] 
public ActionResult DirectDownload(Guid id) 
{ 
    if (Impersonator.ImpersonateValidUser()) 
    { 
     try 
     { 
      var path = "path to file"; 
      if (!System.IO.File.Exists(path)) 
      { 
       return View("filenotfound"); 
      } 

      var bytes = System.IO.File.ReadAllBytes(path); 
      return File(bytes, "application/octet-stream", "FileName"); 
     } 
     catch (Exception e) 
     { 
      Log.Exception(e); 
     }finally 
     { 
      Impersonator.UndoImpersonation(); 
     } 
    } 
    return View("filenotfound"); 
} 

ऊपर कोड के साथ समस्या सिर्फ मैं स्मृति में पूरी फ़ाइल को पढ़ने के लिए है कि है और मैं बहुत बड़ी फ़ाइलें के साथ काम किया जा रहा हूँ, तो यह एक नहीं है अच्छा समाधान। लेकिन अगर मैं इन 2 लाइनों की जगह:

var bytes = System.IO.File.ReadAllBytes(path); 
return File(bytes, "application/octet-stream", "FileName"); 
इस के साथ

:

return File(path, "application/octet-stream", "FileName"); 

यह काम नहीं करता और मैं त्रुटि संदेश मिलता है:

पथ 'ग तक पहुंच: \ परियोजना \ अपलोड \ 1 \ aa2bcbe7-ea99-499d-add8-c1fdac561b0e \ शीर्षक रहित 2.csv 'अस्वीकार कर दिया गया है।

मुझे लगता है कि फ़ाइल परिणामों का उपयोग पथ के साथ करते हुए, अनुरोध पाइपलाइन में बाद में फ़ाइल को खोलने का प्रयास करता है जब मैंने पहले से ही प्रतिरूपण को पूर्ववत कर दिया है।

याद रखें, प्रतिरूपण कोड काम करता है क्योंकि मैं बाइट्स सरणी में फ़ाइल को पढ़ सकता हूं। मैं क्या करना चाहता हूं हालांकि क्लाइंट को फाइल स्ट्रीम कर रहा है।

कोई विचार यह है कि मैं इसके आसपास कैसे काम कर सकता हूं?

अग्रिम धन्यवाद।

उत्तर

4

आप एक कस्टम FilePathResult लिखने का प्रयास हो सकता है:

public class ImpersonatingFileResult : FilePathResult 
{ 
    public ImpersonatingFileResult(string fileName, string contentType) 
     : base(fileName, contentType) 
    { } 

    protected override void WriteFile(HttpResponseBase response) 
    { 
     // TODO : Start impersonation 
     response.TransmitFile(FileName); 
     // TODO : Rollback impersonation 
    } 
} 

और अपने नियंत्रक में:

return new ImpersonatingFileResult(path, "application/octet-stream"); 
+0

यह बहुत अच्छा काम करता है। मैंने इसे थोड़ा बदल दिया क्योंकि मुझे अपवाद मिल रहा था ... Impersonator.ImpersonateValidUser(); Response.WriteFile (फ़ाइल का नाम); response.Flush(); प्रतिक्रिया। अंत(); Impersonator.UndoImpersonation(); – Emad

+0

हां, यह एक अच्छी शुरुआत है।हालांकि, यह आईआईएस के कुछ संस्करणों में "अमान्य हैंडल" त्रुटियों को फेंक देगा, जो फ़ाइल की सेवा करने पर आधारित हैं (और प्रतिरूपण के आधार पर नहीं।) – Greg

1

मैं डैरिन के जवाब पसंद है, लेकिन यह प्रतिरूपण तर्क को छोड़ देता है, और यह एक त्रुटि फेंकता आईआईएस 7 में ...

तो, मैंने एन का उपयोग करके प्रतिरूपण कोड जोड़ा पैकेज पैकेज सरलकरण

इसके अलावा, एक अवैध हैंडल त्रुटि को रोकने के लिए आईआईएस 7 के लिए कुछ बदलाव फेंक दिए गए थे।

public class ImpersonatingFileResult : FilePathResult 
{ 
    public ImpersonatingFileResult(string fileName, string contentType) 
     : base(fileName, contentType) 
    { } 

    protected override void WriteFile(HttpResponseBase response) 
    { 
     using (SimpleImpersonation.Impersonation.LogonUser(domain: "SomeDomain", username: "SomeUser", password: "SomePassword", logonType: SimpleImpersonation.LogonType.NewCredentials)) 
     { 
      response.Clear(); 
      response.ContentType = base.ContentType; 
      response.AddHeader("Content-Disposition", "attachment; filename=" + System.IO.Path.GetFileName(base.FileName)); 
      response.TransmitFile(FileName); 
      response.Flush(); 
     } 
    } 

और फिर नियंत्रक से इसे का उपयोग:

 return new ImpersonatingFileResult(someFilePath, "Application/pdf"); 

ऊपर फ़ाइल डाउनलोड करने के लिए है, लेकिन अगर आप इसे प्रदर्शित करना चाहते हैं, तो आप "इनलाइन" निर्दिष्ट करने की आवश्यकता।

  response.Clear(); 
      response.ContentType = base.ContentType; 
      response.AddHeader("Content-Disposition", "inline; filename=\"" + System.IO.Path.GetFileName(base.FileName) + "\""); 
      response.TransmitFile(FileName); 
      response.Flush(); 
+0

यह एक अच्छा जवाब है, धन्यवाद! –

संबंधित मुद्दे