0

I have download files by returning as stream like below using WCF rest service.

 Stream stream = null;          
            var directoryInformation = CommonServices.Utility.DirectoryHelper.GetTempFolderRootLocation();
            string newFolderPath = directoryInformation + "\\Attachments\\" + Guid.NewGuid();
            try
            {

                Directory.CreateDirectory(newFolderPath);
                DataSet getDocumentContent = GetDocumentContent(engagementId, documentId);
                var fileName = getDocumentContent.Tables[0].Rows[0]["Fullname"] as string;
                var byteData= getDocumentContent.Tables[0].Rows[0]["FilestreamContent"] as byte[];
                string fullPath = newFolderPath + "\\" + fileName;        
                using (var fileStream = new FileStream(fullPath, FileMode.Create))
                {
                    if (byteData != null)
                    {
                        fileStream.Write(byteData,0,byteData.Length);
                        fileStream.Close();
                    }

                    if (WebOperationContext.Current != null)
                    {
                        WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream";
                        WebOperationContext.Current.OutgoingResponse.Headers.Add("content-disposition","inline; filename=" + fileName);
                    }
                }
                stream = File.OpenRead(fullPath);
                return stream;
            }
            catch (Exception exception)
            {

                return null;
            }

The above code works perfectly and can download the file in browser. But i have to delete the file after return the stream. So i have try to close and delete the file including the directory in finally block like below

   finally
            {
                if (stream != null) stream.Close();
                Directory.Delete(newFolderPath, true);
            } 

Full Method code

 public Stream DownloadAttachment(string engagementId, string documentId)
        {
            Stream stream = null;          
            var directoryInformation = CommonServices.Utility.DirectoryHelper.GetTempFolderRootLocation();
            string newFolderPath = directoryInformation + "\\Attachments\\" + Guid.NewGuid();
            try
            {

                Directory.CreateDirectory(newFolderPath);
                DataSet getDocumentContent = GetDocumentContent(engagementId, documentId);
                var fileName = getDocumentContent.Tables[0].Rows[0]["Fullname"] as string;
                var byteData= getDocumentContent.Tables[0].Rows[0]["FilestreamContent"] as byte[];
                string fullPath = newFolderPath + "\\" + fileName;        
                using (var fileStream = new FileStream(fullPath, FileMode.Create))
                {
                    if (byteData != null)
                    {
                        fileStream.Write(byteData,0,byteData.Length);
                        fileStream.Close();
                    }

                    if (WebOperationContext.Current != null)
                    {
                        WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream";
                        WebOperationContext.Current.OutgoingResponse.Headers.Add("content-disposition","inline; filename=" + fileName);
                    }
                }
                stream = File.OpenRead(fullPath);
                return stream;
            }
            catch (Exception exception)
            {

                return null;
            }
           finally
            {
                if (stream != null) stream.Close();
                Directory.Delete(newFolderPath, true);
            }
        }

After adding this code file is not downloaded in client.Is there any way to delete the file?Please help me to resolve this

Jameel Moideen
  • 7,542
  • 12
  • 51
  • 79
  • 1
    Did you add this finally block at the end of the mentioned method? If so, `Close` will dispose the same stream you're trying to return. – Yuval Itzchakov Nov 14 '14 at 10:16
  • could you please look at the source code.i have updated my question by adding the full method – Jameel Moideen Nov 14 '14 at 10:19
  • 1
    You're trying to return a fileStream to a deleted file? – James Nov 14 '14 at 10:20
  • actuall i have return stream after reading a file from server so browser will download this file based on the content type. But after return the stream i have to delete that file. When i try to delete this file without close it shows an exception file is used by another process – Jameel Moideen Nov 14 '14 at 10:24
  • You can't return a `FileStream` to a file which you want to delete because the `FileStream` will hold a handle to that file. Why not return a byte[] with the file instead? – Yuval Itzchakov Nov 14 '14 at 10:25
  • See how try catch finally with return statement works [here](http://stackoverflow.com/questions/421797/what-really-happens-in-a-try-return-x-finally-x-null-statement) – b2zw2a Nov 14 '14 at 10:27
  • but the code is working fine and downloaded the file in browser. The only pblm is when i try to close in finally i think the stream get clear – Jameel Moideen Nov 14 '14 at 10:27
  • It gets disposed when you call `stream.Close()`. You need to re-think what you're doing. – Yuval Itzchakov Nov 14 '14 at 10:28
  • is there any way to achieve the download and delete functionality together? – Jameel Moideen Nov 14 '14 at 10:29
  • Do you have to return a `Stream`? – Yuval Itzchakov Nov 14 '14 at 10:35
  • Yes.I have to return the stream else it will not download the file in browser – Jameel Moideen Nov 14 '14 at 10:36

2 Answers2

1

You can delete the file in OperationContext.OperationCompleted as shown in http://devdump.wordpress.com/2008/12/07/disposing-return-values/

OperationContext clientContext = OperationContext.Current;
clientContext.OperationCompleted += new EventHandler(delegate(object sender, EventArgs args)
   {
          if (stream != null) stream.Close();
          Directory.Delete(newFolderPath, true);
   });
Simon Taylor
  • 207
  • 1
  • 2
  • 6
0

Change your method to this.

public void DownloadAttachment(string engagementId, string documentId, Action<Stream> processFile)

and instead of returning the stream call the processFile Action

processFile(stream);

This way you're not leaving the method in order to process the file. You will need to restructure the calling code in order to process the file though.

James
  • 9,774
  • 5
  • 34
  • 58