File Download (English)

File Download

Sunday, 29 February 2004

//

1 minute read

ASP.NET has a problem with file downloads...basically if you use Response.WriteFile(fileName), the entire file is buffered in memory before its' downloaded - this is NOT good for scalability. To get round that proble, here's some code which could be used for file download - it looks the file download, only downloading chunks at a time. Also checks that the client is connected before sending the next chunk...


private void DownloadFile(Guid itemId)
        {
            //Where to start in the file
            long startPos = 0; 
            //How big a chunk to download in each iteration
            long chunkSize = 20480;
            //Use the id to retreive the resource files details
            using(SqlDataReader reader=SqlExtra.ExecuteReader("GetResource", itemId))
            {
                try
                {
                    if(reader.Read())
                    {
                        //Get the file details we need to save a copy to the client
                        string fileExtension=reader["FileTypeExtension"].ToString();
                        string fileNameClient=reader["FileName"].ToString();
                        string fileNameServer=Server.MapPath(string.Format(@"Uploads/{0}{1}", itemId.ToString(),  fileExtension));
                        FileInfo file=new FileInfo(fileNameServer);    
                        //Only proceed with the download if the file physically exists
                        if (file.Exists)
                        {
                            
                            //Setup the Response object to allow file downloads
                            Response.Clear();
                            Response.ContentType = "application/octet-stream";
                            //Attach the file to the response stream.
                            Response.AddHeader("Content-Disposition", string.Format("{0}{1}", "attachment; filename=", fileNameClient));
                            Response.AddHeader("Content-Length",file.Length.ToString());
                            long fileSize = file.Length;
                            try
                            {
                                while(startPos < file.Length)
                                {
                                    if(Response.IsClientConnected)
                                    {
                                        //write the file to the client
                                        if(startPos + chunkSize > fileSize)
                                        {
                                            chunkSize = fileSize - startPos;
                                        }
                                        Response.WriteFile(fileNameServer,startPos,chunkSize);    
                                        Response.Flush();
                                        startPos += chunkSize;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                
                            }
                            catch(Exception ex)
                            {
                                ExceptionManager.Publish(ex);
                            }
                            Response.End();
                        }
                        else
                        {
                            //display an error message
                            StatusMessage.Text=fileNameClient;
                        }
                    
                    }
                }
                catch(Exception ex)
                {
                    if(ex.GetType() != typeof(System.Threading.ThreadAbortException))
                    {
                        ExceptionManager.Publish(ex);
                    }
                }
            }
        }

Hope you find it useful... sorry about the formatting...seems this page isn't very flexible...hmm...

logo

© 2025 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.