Click here to Skip to main content
15,890,350 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I have my own dedicated server. With 100 Mbps download connection to my users to download files.
I have a small 60KB text file that I am constantly converting into zip file with 8KB in size on my server. So my user can easily download this file with dial up connection very fast.
Problem here is that whenever my clients tried to download this file using http protocol through my client application, This zip file is blocked on server until client finishes his download. In between this blocked time I can't update zip file on server.
Now problem arises more when 200 clients simultaneously download this zip file each second. My C# code of zipping this file blocked indefinably on server. And I can't update this zip file in realtime mode.

I used c# code of try & catch statement. But it only fall into catch code segment each time any client downloading this file.

My question is how to allow zipping of this text file in server using C# in realtime mode & still allow 1000 clients to access this file in realtime mode.

I am using C#, ASP .NET web services on my server.

Please let me know if you have any solution to this problem.
Posted
Comments
Timberbird 14-Sep-12 3:24am    
Could you show the code that sends file to client? If you use the stream that is only closed when file is sent to client, you could consider reading file to memory first, then closing file and sending content to client from memory.
Anyway, first suggestion that comes to my mind is to store file content in application-level cache, renewing it periodically

1 solution

1. Read your file and store in memory stream.
2. Zip the stream and allow users to to download the zipped stream only.
U can use Open Source SharpzipLib for zipping it:
C#
/// <summary>
/// Get MemoryStream stream of the file path specified
/// </summary>
/// <param name="FileNamePath">File System full path and file name</param>
private MemoryStream GetMemoryStream(string filepath, out Exception e)
{
    e = null;
    MemoryStream dest = new MemoryStream();
    try
    {

        using (Stream source = File.OpenRead(filepath))
        {
            dest.SetLength(source.Length);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
            {
                dest.Write(buffer, 0, bytesRead);
            }
            dest.Flush();
            dest.Position = 0;
            return dest;
        }
    }
    catch (Exception ex)
    {
        e = new Exception("GetMemoryStream : " + ex.ToString());
        return (MemoryStream)null;
    }
}
        /// <summary>
        /// Get byte array fron MemoryStream stream
        /// </summary>
        /// <param name="stream">Stream to read</param>
        public byte[] ReadToEnd(Stream stream)
        {
            long originalPosition = 0;

            if (stream.CanSeek)
            {
                originalPosition = stream.Position;
                stream.Position = 0;
            }

            try
            {
                byte[] readBuffer = new byte[4096];

                int totalBytesRead = 0;
                int bytesRead;

                while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
                {
                    totalBytesRead += bytesRead;

                    if (totalBytesRead == readBuffer.Length)
                    {
                        int nextByte = stream.ReadByte();
                        if (nextByte != -1)
                        {
                            byte[] temp = new byte[readBuffer.Length * 2];
                            Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                            Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                            readBuffer = temp;
                            totalBytesRead++;
                        }
                    }
                }

                byte[] buffer = readBuffer;
                if (readBuffer.Length != totalBytesRead)
                {
                    buffer = new byte[totalBytesRead];
                    Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
                }
                return buffer;
            }
            finally
            {
                if (stream.CanSeek)
                {
                    stream.Position = originalPosition;
                }
            }
        }

        private byte[] ZipToByteArray(MemoryStream memStreamIn, string zipEntryName, string password)
        {

            MemoryStream outputMemStream = new MemoryStream();
            ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
            zipStream.Password = password;
            zipStream.SetLevel(3); //0-9, 9 being the highest level of compression

            ZipEntry newEntry = new ZipEntry(zipEntryName);
            newEntry.DateTime = DateTime.Now;


            zipStream.PutNextEntry(newEntry);

            StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
            zipStream.CloseEntry();

            zipStream.IsStreamOwner = false;	// False stops the Close also Closing the underlying stream.
            zipStream.Close();			        // Must finish the ZipOutputStream before using outputMemStream.

            outputMemStream.Flush();
            outputMemStream.Position = 0;
            return ReadToEnd(outputMemStream);
        }


And finally the download method:
C#
void Download(string fileName, byte[] data)
{
try
    {
        HttpResponse response = HttpContext.Current.Response;
        response.Clear();
        response.ClearContent();
        response.ClearHeaders();
        response.Buffer= true;
        response.AddHeader("Content-Disposition","attachment;filename=\"" + fileName  + "\"");
        response.BinaryWrite(data);
        response.End();
    }
    catch(Exception ex)
    {
    }
}
 
Share this answer
 
Comments
Nilesh bhope 14-Sep-12 3:28am    
Hi Kuthuparakkal,

Thanks for replying quickly. I will try this code in my apps. I will post whether it worked correctly.
Nilesh bhope 14-Sep-12 4:23am    
Hi,

I am getting error StreamUtils doesn't exist & zipStream.Password method not available. I used & defined sharpzip dll reference correctly. All other references working like "ICSharpCode.SharpZipLib.Zip.ZipOutputStream" & "ICSharpCode.SharpZipLib.Zip.ZipEntry" . Might be my dll is old. Downloaded again from shapzip website correct dll. But same problem.

Here are C# sharpzip declaretion:

using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
Kuthuparakkal 14-Sep-12 4:37am    
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;
is enough!
I am using this method day-today to post 1000 of files to SharePoint. Works very well!
Nilesh bhope 14-Sep-12 4:45am    
You are right. I was using old sharpzip dll from their samples on website. I used correct dll. IT worked. I still some question regarding output file & how to download.

Here is my similar code which works using your above aproach.

Exception ERR = null;
MemoryStream md = GetMemoryStream(@"C:\InetPub\wwwroot\File.txt", out ERR);
ZipToByteArray(md, "example.zip", "nilu");

Now i was expecting zip file to be in my project debug folder or wwwroot folder. But no files created on my server physical disk. Is this zip file created in only in memory of my server. If yes how can my client application access this zipped memory stream over internet. In your above example for downloading this zipped stream, Where can I add my server address e.g 155.131.535.231 in client application code?
Kuthuparakkal 14-Sep-12 4:51am    
It's in memory and and you said it's jus 8KB... And you see the Download method there, it needs byte array and the file name you would like to add(eg: example.zip). Now from a button click event on Download pass the filepath to get MemoryStream and Zip it to byte array, and call Download method with the byte array and filename.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900