2013-04-10 6 views
7

लौटने के बाद अस्थायी फ़ाइलों को हटा नहीं सकता है मेरे पास एक सी # एमवीसी अनुप्रयोग में एक फ़ंक्शन है जो एक अस्थायी निर्देशिका और एक अस्थायी फ़ाइल बनाता है, फिर फ़ाइलस्ट्रीम का उपयोग कर फ़ाइल खोलता है, फ़ाइलस्ट्रीम को कॉलिंग फ़ंक्शन पर लौटाता है, और उसके बाद इसकी आवश्यकता होती है अस्थायी फ़ाइलों को हटा दें। हालांकि, मुझे नहीं पता कि temp निर्देशिका और फ़ाइल को कैसे हटाया जाए क्योंकि यह हमेशा यह कहता है कि "प्रक्रिया फ़ाइल तक नहीं पहुंच सकती क्योंकि यह किसी अन्य प्रक्रिया द्वारा उपयोग की जा रही है।" मैंने यही कोशिश की, लेकिन फाइलस्ट्रीम अभी भी अंत में ब्लॉक में temp फ़ाइल का उपयोग कर रहा है। मैं फ़ाइलस्ट्रीम कैसे वापस कर सकता हूं और अस्थायी फ़ाइलों को हटा सकता हूं?फ़ाइलस्ट्रीम

public FileStream DownloadProjectsZipFileStream() 
{ 
    Directory.CreateDirectory(_tempDirectory); 
    // temporary file is created here 
    _zipFile.Save(_tempDirectory + _tempFileName); 

    try 
    { 
     FileStream stream = new FileStream(_tempDirectory + _tempFileName, FileMode.Open); 
     return stream; 
    } 
    finally 
    { 
     File.Delete(_tempDirectory + _tempFileName); 
     Directory.Delete(_tempDirectory); 
    } 
} 

समारोह FileStream इस तरह दिखता है के लिए वापस आ गया है:

public ActionResult DownloadProjects() 
{ 
    ProjectDownloader projectDownloader = new ProjectDownloader(); 

    FileStream stream = projectDownloader.DownloadProjectsZipFileStream(); 
    return File(stream, "application/zip", "Projects.zip"); 
} 

अद्यतन: मैं ज़िप फ़ाइल उल्लेख करना भूल गया 380 MB है। मेमोरीस्ट्रीम का उपयोग करते समय मुझे स्मृति अपवाद से सिस्टम मिल जाता है।

+0

'FileStream' फ़ाइल खुला, क्यों तुम भी फ़ाइल को नष्ट करने में सक्षम हो की उम्मीद करते हैं है? इससे लौटाया गया 'फाइलस्ट्रीम' अनुपयोगी होगा। –

+0

_zipFile का प्रकार क्या है? –

+2

आपको वास्तव में फ़ाइल की आवश्यकता नहीं है, इसके बजाय मेमोरी स्ट्रीम में सहेजें। –

उत्तर

4

आप एक आवरण वर्ग कि Stream अनुबंध लागू करता है बना सकते हैं और उस FileStream आंतरिक रूप से, साथ ही फ़ाइल का पथ को बनाए रखने में शामिल है।

सभी मानक Stream विधियों और गुणों को FileStream उदाहरण में पास किया जाएगा।

जब यह रैपर वर्ग Dispose डी है, तो आप (Dispose लपेटकर FileStream में) फ़ाइल को हटा दें।

+0

यही वह है जो मैंने कर दिया। मैंने अभी फ़ाइलस्ट्रीम और टेम्पल फ़ाइल/निर्देशिका पथ में पारित कन्स्ट्रक्टर में विस्तार किया है, और निपटान विधि में मैंने temp फ़ाइल और निर्देशिका के लिए डिलीट कोड जोड़ा है। सलाह के लिये धन्यवाद! – Bumper

+1

@ बम्बर, क्या आप अपना कोड पोस्ट कर सकते हैं? – RayLoveless

2

समस्या यह है कि आप प्रतिक्रिया में लिखे जाने के बाद ही फ़ाइल को हटा सकते हैं और फ़ाइल को कार्रवाई से वापस लौटने के बाद ही फ़ाइलस्ट्रीमResult द्वारा लिखा जाता है।

फ़ाइल करने के लिए एक तरीका है FileResult का उप-वर्ग बनाना जो फ़ाइल को हटा देगा।

FilePathResult उपclass करना आसान है ताकि कक्षा के पास फ़ाइल नाम तक पहुंच हो।

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

    protected override void WriteFile(HttpResponseBase response) 
    { 
     base.WriteFile(response); 
     File.Delete(FileName); 
     Directory.Delete(FileName); 
    } 
} 

नोट: मैंने उपर्युक्त परीक्षण नहीं किया है। इसका उपयोग करने से पहले सभी कीड़े को हटा दें।

अब की तरह कुछ करने के लिए नियंत्रक कोड बदलने के लिए:

public ActionResult DownloadProjects() 
{ 
    Directory.CreateDirectory(_tempDirectory); 
    // temporary file is created here 
    _zipFile.Save(_tempDirectory + _tempFileName); 

    return new FilePathWithDeleteResult(_tempDirectory + _tempFileName, "application/zip") { FileDownloadName = "Projects.zip" }; 
} 
3

मैंने Damien_The_Unbeliever (स्वीकृत उत्तर) की सलाह का उपयोग किया, इसे लिखा, और यह खूबसूरती से काम किया। बस सोचा था कि मैं वर्ग का हिस्सा हैं:

public class BurnAfterReadingFileStream : Stream 
{ 
    private FileStream fs; 

    public BurnAfterReadingFileStream(string path) { fs = System.IO.File.OpenRead(path); } 

    public override bool CanRead { get { return fs.CanRead; } } 

    public override bool CanSeek { get { return fs.CanRead; } } 

    public override bool CanWrite { get { return fs.CanRead; } } 

    public override void Flush() { fs.Flush(); } 

    public override long Length { get { return fs.Length; } } 

    public override long Position { get { return fs.Position; } set { fs.Position = value; } } 

    public override int Read(byte[] buffer, int offset, int count) { return fs.Read(buffer, offset, count); } 

    public override long Seek(long offset, SeekOrigin origin) { return fs.Seek(offset, origin); } 

    public override void SetLength(long value) { fs.SetLength(value); } 

    public override void Write(byte[] buffer, int offset, int count) { fs.Write(buffer, offset, count); } 

    protected override void Dispose(bool disposing) 
    { 
     base.Dispose(disposing); 
     if (Position > 0) //web service quickly disposes the object (with the position at 0), but it must get rebuilt and re-disposed when the client reads it (when the position is not zero) 
     { 
      fs.Close(); 
      if (System.IO.File.Exists(fs.Name)) 
       try { System.IO.File.Delete(fs.Name); } 
       finally { } 
     } 
    } 
} 
4

यहाँ ऊपर का एक cutdown संस्करण है कि मैं का उपयोग करें:

public class DeleteAfterReadingStream : FileStream 
{ 
    public DeleteAfterReadingStream(string path) 
     : base(path, FileMode.Open) 
    { 
    } 

    protected override void Dispose(bool disposing) 
    { 
     base.Dispose(disposing); 
     if (File.Exists(Name)) 
      File.Delete(Name); 
    } 
} 
0

मैं विधि @hwiechers ने सुझाव दिया उपयोग करें, लेकिन एक ही तरीका है इसे बनाने के लिए फ़ाइल को हटाने से पहले प्रतिक्रिया स्ट्रीम को बंद करना है।

यहां स्रोत कोड है, ध्यान दें कि मैं इसे हटाने से पहले स्ट्रीम को फ्लश करता हूं।

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

    protected override void WriteFile(HttpResponseBase response) 
    { 
     base.WriteFile(response); 
     response.Flush(); 
     File.Delete(FileName); 
    } 

} 

और यहाँ कैसे नियंत्रक इसे कहते माना जाता है:

public ActionResult DownloadFile() { 

    var tempFile = Path.GetTempFileName(); 

    //do your file processing here... 
    //For example: generate a pdf file 

    return new FilePathAutoDeleteResult(tempFile, "application/pdf") 
    { 
     FileDownloadName = "Awesome pdf file.pdf" 
    }; 
} 
संबंधित मुद्दे