I have written a code for enabling multiple connection download(Range-Requests) through Internet Download Manager and it works fine in my local system(it is able to create multiple connections and download a file.) but it's not able to create more than one connection in my server (Windows 2012 R2).
Also, when I keep a file on download and try to open another webpage of my application, it shows loading and does not open(until I cancel the download or let the download to complete.)
Below is my downloader code:
public ActionResult getFile()
{
System.IO.FileStream iStream = null;
var response = System.Web.HttpContext.Current.Response;
var request = System.Web.HttpContext.Current.Request;
// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[10000];
int length1;
long dataToRead;
try
{
//File path.
string finalPath = #"C:\myfiles\abc.txt";
long size, start, end, length, fp = 0;
using (StreamReader reader = new StreamReader(finalPath))
{
size = new System.IO.FileInfo(finalPath).Length;
start = 0;
end = size - 1;
length = size;
response.AddHeader("Accept-Ranges", "0-" + size);
if (!String.IsNullOrEmpty(request.Headers["Range"]))
{
long anotherStart = start;
long anotherEnd = end;
string[] arr_split = request.Headers["Range"].Split(new char[] { Convert.ToChar("=") });
string range = arr_split[1];
// Make sure the client hasn't sent us a multibyte range
if (range.IndexOf(",") > -1)
{
// (?) Shoud this be issued here, or should the first
// range be used? Or should the header be ignored and
// we output the whole content?
response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
throw new HttpException(416, "Requested Range Not Satisfiable");
}
// If the range starts with an '-' we start from the beginning
// If not, we forward the file pointer
// And make sure to get the end byte if spesified
if (range.StartsWith("-"))
{
// The n-number of the last bytes is requested
anotherStart = size - Convert.ToInt64(range.Substring(1));
}
else
{
arr_split = range.Split(new char[] { Convert.ToChar("-") });
anotherStart = Convert.ToInt64(arr_split[0]);
long temp = 0;
anotherEnd = (arr_split.Length > 1 && Int64.TryParse(arr_split[1].ToString(), out temp)) ? Convert.ToInt64(arr_split[1]) : size;
}
/* Check the range and make sure it's treated according to the specs.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
*/
// End bytes can not be larger than $end.
anotherEnd = (anotherEnd > end) ? end : anotherEnd;
// Validate the requested range and return an error if it's not correct.
if (anotherStart > anotherEnd || anotherStart > size - 1 || anotherEnd >= size)
{
response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
throw new HttpException(416, "Requested Range Not Satisfiable");
}
start = anotherStart;
end = anotherEnd;
fp = reader.BaseStream.Seek(start, SeekOrigin.Begin);
length = end - start + 1; // Calculate new content length
response.StatusCode = 206;
}
}
var fileName1 = Path.GetFileName(finalPath);
var fileNameUrlEncoded = HttpUtility.UrlEncode(fileName1, System.Text.Encoding.UTF8);
// Notify the client the byte range we'll be outputting
response.ContentType = "application/octet-stream";
response.AddHeader("Content-Disposition", "attachment;filename=" +
fileNameUrlEncoded.Replace("+", "%20"));
response.AddHeader("Connection", "Keep-Alive");
response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
response.AddHeader("Content-Length", length.ToString());
//response.WriteFile(finalPath, fp, length);
//response.End();
//As WriteFile() method does not work for huge files, thus using
//Chunk downloading below.
string filename = System.IO.Path.GetFileName(finalPath);
iStream = new FileStream(finalPath, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read,4096,true);
// Total bytes to read:
dataToRead = length;
iStream.Position = start;
while (dataToRead > 0)
{
// Verify that the client is connected.
if (Response.IsClientConnected)
{
// Read the data in buffer.
length1 = iStream.Read(buffer, 0, 10000);
// Write the data to the current output stream.
Response.OutputStream.Write(buffer, 0, length1);
// Flush the data to the HTML output.
Response.Flush();
buffer = new Byte[10000];
dataToRead = dataToRead - length1;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception e)
{
TempData["Message"] = "error: " + e.Message;
return View();
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
response.Close();
}
return View();
}
I am suspecting some server configuration issues that is causing the above issue. Can anyone help me to know what configuration changes might cause this issue.
Thanks in Advance.
Related
I am re-developing an app for a scanner used for stocktakes to allow it to work while offline. In order to do so, I need to be able to download a file from a laptop which is acting as a server. I got to a point at which it works, but only downloads that are of size 9.53mb max. How can I tweak the code to allow for larger files. I would need to allow for a maximum size of around 30mb.
Here is my code:
try
{
string full_url = App.prouductUrl + App.stStocktakeId + ".db";
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(full_url);
httpRequest.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
System.IO.Stream dataStream = httpResponse.GetResponseStream();
// Dim str As Stream = cdsMobileLibrary2.http_download.getfile(filename)
//50 meg
byte[] inBuf = new byte[10000001];
int bytesToRead = Convert.ToInt32(inBuf.Length);
int bytesRead = 0;
while (bytesToRead > 0)
{
int n = dataStream.Read(inBuf, bytesRead, bytesToRead);
if (n == 0)
{
break; // TODO: might not be correct. Was : Exit While
}
bytesRead += n;
bytesToRead -= n;
}
FileStream fstr = new FileStream(#"\productdb\" + App.stStocktakeId + ".db", FileMode.OpenOrCreate, FileAccess.Write);
fstr.Write(inBuf, 0, bytesRead);
dataStream.Close();
fstr.Close();
string size = loginRes.getFromJSON("size");
FileInfo fi = new FileInfo(#"\productdb\" + App.stStocktakeId + ".db");
MessageBox.Show("File Size is:" + fi.Length + "Compared to:" + size);
}
catch { }
today while doing a logic for downloading large size files, i am facing an error. For downloading what my logic is am spltting the file into 10KB chunks and then integrating it and is downloading.While downloading what happening is like each time am reducing the total size by 10KB , but once the remaining length is less than 10KB my download is getting interuppted. Please find the below code of mine and let me know if any change needed in my logic.
protected void btnDownload_Click(object sender, EventArgs e)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
System.IO.Stream iStream = null;
// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[10000];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
// Identify the file to download including its path.
string filepath = "C:\\Users\\GZT00000000000001020\\Desktop\\123.zip";
// Identify the file name.
string filename = System.IO.Path.GetFileName(filepath);
try
{
iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
dataToRead = iStream.Length;
Page.Response.ContentType = "application/octet-stream";
Page.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (Page.Response.IsClientConnected)
{
if( (dataToRead < 10000) && (dataToRead!=-1))
{
length = (int)dataToRead;
buffer = new Byte[length];
dataToRead = -1;
}
else
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 10000);
}
// Write the data to the current output stream.
Page.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
Page.Response.Flush();
if (dataToRead > 10000)
{
buffer = new Byte[10000];
dataToRead = dataToRead - length;
}
else if(dataToRead!=-1)
{
length =(int)dataToRead ;
buffer = new Byte[length];
}
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
Page.Response.Write("Error : " + ex.Message);
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
Page.Response.Close();
}
});
}
You don't call iStream.Read in the branch where dataToRead < 10000
I have tried every solution I could find but nothing seems to work. Anything other than text files becomes corrupted; someone said that TCP can't send more than 8KB, so I tried to fix the problem and I think I did. Now, when I send a text file (no matter what size it is), it reaches perfectly but anything else gets corrupted. I know the code for the cutting is expensive to performance but I am going to think about that later.
Here is my sender code:
private string SendFile(string tosend, string tosendname)
{
ipadd = IPAddress.Parse(textBox2.Text);
ep = new IPEndPoint(ipadd, 6112);
Sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Sender.Connect(ep);
Thread.Sleep(100);
byte[] filetosend = System.IO.File.ReadAllBytes(tosend);
FileStream fs = new FileStream(tosend, FileMode.Open, FileAccess.Read);
//Read byte from image
fs.Read(filetosend, 0, filetosend.Length);
fs.Flush();
fs.Close();
int countt = filetosend.Count();
int dividedcount = countt / 7000;
Sender.Send(Encoding.ASCII.GetBytes("filesize#" + filetosend.Count().ToString()));
Thread.Sleep(500);
List<byte> cuttedtosend = new List<byte>();
for (int counti = 0; counti < dividedcount; counti++)
{
cuttedtosend = new List<byte>();
for (int index = 0; index < 7000; index++)
{
cuttedtosend.Add(filetosend[(filetosend.Count() - countt) + index]);
}
Sender.Send(cuttedtosend.ToArray());
Thread.Sleep(100);
countt -= 7000;
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Countt = " + countt + "\n"); });
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti + "\n"); });
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Done"); });
cuttedtosend = new List<byte>();
for (int index = filetosend.Count() - countt; index < filetosend.Count(); index++)
{
//richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(index + "this is 2 \n"); });
cuttedtosend.Add(filetosend[index]);
}
Sender.Send(cuttedtosend.ToArray());
countt -= countt;
return "";
}
And here is my receive code:
private async void StartReceiving()
{
List<byte> neededbytes = new List<byte>();
receivedbyte = new byte[InputForm.s];
Receiver.Bind(new IPEndPoint(IPAddress.Parse("0"), 6112));
Receiver.Listen(1000);
string filename = "Downloadedfile";
bool cont = false;
while (true)
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Client = Receiver.Accept();
int filesize = 0;
byte[] receivechecker = new byte[100];
Client.Receive(receivechecker);
if(Encoding.ASCII.GetString(receivechecker).Contains("filesize#"))
{
filesize = Convert.ToInt32(Encoding.ASCII.GetString(receivechecker).Remove(0, 9));
Client.Receive(receivechecker);
}
if (Encoding.ASCII.GetString(receivechecker).Contains("#100254#"))
{
string[] splttedtext = Encoding.ASCII.GetString(receivechecker.ToArray()).Split('#');
if (splttedtext[0] == "mess")
{
MessageBox.Show(splttedtext[2]);
}
else if (splttedtext[0] == "filename")
{
//MessageBox.Show(splttedtext[2]);
filename = splttedtext[2];
//filename.Replace(#"\", #"/");
cont = true;
}
}
else
{
List<byte> tosave = new List<byte>();
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(filesize.ToString() + "\n"); });
int countt = filesize / 7000;
FileStream writer = File.Create("DownloadedFile.jpg");
for (int counti = 0; counti < countt; counti++)
{
byte[] toadd = new byte[7000];
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti.ToString() + "\n"); });
Client.Receive(toadd);
writer.Write(toadd,0,toadd.Count());
neededbytes.AddRange(toadd);
filesize -= 7000;
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(filesize.ToString() + "\n"); });
byte[] toadds = new byte[filesize];
Client.Receive(toadds);
writer.Write(toadds,0,toadds.Count());
writer.Close();
neededbytes.AddRange(toadds);
filesize -= filesize;
}
}
Thanks in advance :D
Edit:
I just tried Sending a 7mb text file and it reached complete.......
The most immediate problem is that you're saving bytes that you didn't necessarily receive. For example, you have:
for (int counti = 0; counti < countt; counti++)
{
byte[] toadd = new byte[7000];
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti.ToString() + "\n"); });
Client.Receive(toadd);
writer.Write(toadd,0,toadd.Count());
neededbytes.AddRange(toadd);
filesize -= 7000;
}
The documentation for Receive says that the method will receive up to the number of bytes you request. It's not uncommon for it to return fewer bytes than you requested, especially at the end of the file (since it couldn't receive more than the file length).
You need to write:
var bytesRead = Client.Receive(toadd);
writer.Write(toadd, 0, bytesRead); // only write as many bytes as you've read
In general, your code is pretty convoluted, and you have several other possible problems just waiting to bite you. For example, the code that sends the file size sleeps for 500 ms, which just happens to be enough time for the receiver to read just the number of bytes sent. Without that sleep, your code would fail.
You have code to receive the file name, but no code to send it.
I would suggest that you eliminate the ASCII tags and send things in binary. Below is your rewritten Send method.
private string SendFile(string tosend, string tosendname)
{
ipadd = IPAddress.Parse(textBox2.Text);
ep = new IPEndPoint(ipadd, 6112);
Sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Sender.Connect(ep);
byte[] filetosend = System.IO.File.ReadAllBytes(tosend);
byte[] filesizeBytes = BitConverter.GetBytes(filetosend.Length);
Sender.Send(filesizeBytes); // sends the length as an integer
// note: You could use Socket.Send(filetosend) here.
// but I'll show an example of sending in chunks.
int totalBytesSent = 0;
while (totalBytesSent < filetosend.Length)
{
int bytesLeft = filetosend.Length - totalBytesSent;
int bytesToSend = Math.Min(bytesLeft, 7000);
Sender.Send(filetosend, totalBytesSent, bytesToSend);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.Append(totalBytesSent + " bytes sent\n"); });
totalBytesSent += bytesToSend;
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Done"); });
return "";
}
The receiver code is similarly simplified:
private async void StartReceiving()
{
Receiver.Bind(new IPEndPoint(IPAddress.Parse("0"), 6112));
Receiver.Listen(1000);
string filename = "Downloadedfile";
bool cont = false;
while (true)
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Client = Receiver.Accept();
// read the length
byte[] filesizeBytes = new byte[4];
int totalBytesReceived = 0;
while (totalBytesReceived < 4)
{
int bytesRead = Client.Receive(
filesizeBytes, totalBytesReceived, 4-totalBytesReceived);
totalBytesReceived += bytesRead;
}
int filesize = BitConverter.ToInt32(filesizeBytes);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText(filesize.ToString() + "\n"); });
// now read the file
using (FileStream writer = File.Create("DownloadedFile.jpg"))
{
byte[] readBuffer = new byte[7000];
totalBytesReceived = 0;
while (totalBytesReceived < filesize)
{
int bytesToRead = Math.Min(7000, filesize - totalBytesReceived);
int bytesRead = Client.Receive(readBuffer, 0, bytesToRead);
totalBytesRead += bytesRead;
writer.Write(readBuffer, 0, bytesRead);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText("Read " + bytesRead.ToString() + "bytes\n"); });
}
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText("Done. " + totalBytesRead.ToString() + " bytes\n"); });
}
}
If you want to send the file name, then I would suggest converting it to UTF8 (Encoding.UTF8.GetBytes(filename)), then send an int (4 bytes) that says how long it is, and then the buffer. To receive it, read the 4-byte filename length like I showed how to read the file size, then that many bytes for the file name, and convert back to a string (Encoding.UTF8.GetString(bytes, 0, filenameLength)).
Please excuse any typos or minor errors in the code. I'm doing this from memory and trying to keep somewhat with your coding style.
i suspect that you are expecting the same blocks that you send to be received; ie that record boundaries will be preserved. This is not so. TCP guarantees that every byte sent will be received and that order is preserved; but you could do 1 large 10k send and receive 10k 1 byte messages.
I have this download function, and it's working great. BUT with a file with filesize of 1.35gb the download stops at 300 Mb, 382, 400mb or 1.27 Gb. What am I doing wrong? (The download function is made this way, because files need to be hidden, and may not be published on the website.)
public static void downloadFunction(string filename)
{
string filepath = #"D:\texts\New folder\DLfolder\" + filename;
string contentType = "application/x-newton-compatible-pkg";
Stream iStream = null;
// Buffer to read 10K bytes in chunk
//byte[] buffer = new Byte[10000];
// Buffer to read 1024K bytes in chunk
byte[] buffer = new Byte[1048576];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
try
{
// Open the file.
iStream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
HttpContext.Current.Response.ContentType = contentType;
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8));
HttpContext.Current.Response.AddHeader("Content-Length", iStream.Length.ToString());
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (HttpContext.Current.Response.IsClientConnected)
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 10000);
// Write the data to the current output stream.
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
HttpContext.Current.Response.Flush();
buffer = new Byte[10000];
dataToRead = dataToRead - length;
}
else
{
// Prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
HttpContext.Current.Response.Write("Error : " + ex.Message + "<br />");
HttpContext.Current.Response.ContentType = "text/html";
HttpContext.Current.Response.Write("Error : file not found");
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
HttpContext.Current.Response.End();
HttpContext.Current.Response.Close();
}
}
You may have hit the request timeout. Take a note, if file stops downloading after some predetermined amount of time, like 60 or 300 seconds. If that is the case, you can configure timeouts in web.config of your application.
I have a bit of code that uses a Task to transfer a file over a web service. However if the network drops or a timeout occurs it results in an incomplete file. I'm really trying to make this service as reliable as possible, but I'm not really sure where to even really start to add code that will trap when a chunk was not sent, and then attempt to resend it multiple times but also not send the next chunk until that is done. And maybe if it cannot resend that chunk over X times, fail completely and log an event.
Can anyone suggest anything?
Action<Guid, string> action = (smGuid, pubAttFullPath) =>
{
try
{
//Set filename from object
string FileName;
FileName = System.IO.Path.GetFileName(pubAttFullPath.ToString());
//Declare Web Service
TransferFile.TransferFileSoapClient ws_TransferFile = new TransferFile.TransferFileSoapClient();
//
bool transfercompleted = false;
using (FileStream fs = new FileStream(
pubAttFullPath.ToString(),
FileMode.Open,
FileAccess.Read,
FileShare.Read))
{
//Declare Buffers and Counts
byte[] buffer = new byte[49152];
long fileSize = fs.Length;
long totalReadCount = 0;
int readCount;
float percentageComplete = 0;
//Loop and copy file until it changes to not exactly the same byte count as the buffer
//which means the file is about to complete.
while ((readCount = fs.Read(buffer, 0, buffer.Length)) > 0)
{
if (!transfercompleted)
{
totalReadCount += readCount;
byte[] bytesToTransfer;
if (readCount == buffer.Length)
{
//Copy bytes until buffer is different
bytesToTransfer = buffer;
ws_TransferFile.WriteBinaryFile("ABCD", bytesToTransfer, FileName);
percentageComplete = (totalReadCount / (float)fileSize * 100);
percentageComplete = (float)Math.Round(percentageComplete, 2, MidpointRounding.ToEven);
//Update progress to DB
InsertProgress.InsertProgressSoapClient ws_InsertProgress = new InsertProgress.InsertProgressSoapClient();
if (percentageComplete == 10.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 10.0);
}
if (percentageComplete == 20.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 20.0);
}
if (percentageComplete == 30.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 30.0);
}
if (percentageComplete == 40.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 40.0);
}
if (percentageComplete == 50.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 50.0);
}
if (percentageComplete == 60.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 60.0);
}
if (percentageComplete == 70.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 70.0);
}
if (percentageComplete == 80.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 80.0);
}
if (percentageComplete == 90.00)
{
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 90.0);
}
}
else
{
// Only a part is requred to upload,
// copy that part.
List<byte> b = new List<byte>(buffer);
bytesToTransfer = b.GetRange(0, readCount).ToArray();
ws_TransferFile.WriteBinaryFile("ABCD", bytesToTransfer, FileName);
percentageComplete = 100;
//Insert Progress as complete
InsertProgress.InsertProgressSoapClient ws_InsertProgress = new InsertProgress.InsertProgressSoapClient();
ws_InsertProgress.InsertProgressService(smGuid.ToString(), 100);
transfercompleted = true;
fs.Close();
break;
}
}
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.Message.ToString(), EventLogEntryType.Error);
}
Web service is bad idea for file transfer. I used it few times, but amount of additional data transfered is making size of transfered data 1,5-2 times bigger then sending file using simple handler. Handler will allow you to the same without issues. It causes al lot of problem with proper progress handling and resume. You realy should reconsider using httphandler. If you like to use webservice, here is good example:
http://msdn.microsoft.com/en-us/library/ms172362%28v=vs.85%29.aspx
If you decide to use IHttpHandler see:
http://msdn.microsoft.com/en-us/library/ms228090%28v=vs.100%29.aspx
And then you can use following piece of code to proper handle retry/resume:
using (Stream stream = new FileStream(
pubAttFullPath.ToString(),
FileMode.Open,
FileAccess.Read,
FileShare.Read))
{
context.Response.AddHeader("Accept-Ranges", "bytes");
context.Response.Buffer = false;
if (context.Request.Headers["Range"] != null)
{
context.Response.StatusCode = 206;
string[] range = context.Request.Headers["Range"].Split(new[] { '=', '-' });
startBytes = Convert.ToInt32(range[1]);
}
int dataToRead = size - startBytes;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Length", dataToRead.ToString());
context.Response.AddHeader("Connection", "Keep-Alive");
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8));
if (startBytes > 0)
{
context.Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, size - 1, size));
stream.Seek(startBytes, SeekOrigin.Begin);
}
while (dataToRead > 0)
{
// Verify that the client is connected.
if (context.Response.IsClientConnected)
{
// Read the data in buffer.
int length = stream.Read(buffer, 0, buffer.Length);
// Write the data to the current output stream.
context.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
context.Response.Flush();
dataToRead = dataToRead - length;
}
else
{
// prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}