private void SendFileContent(File422 file, WebRequest req) { byte[] buffer = new byte[1024]; //1kb buffer StringBuilder sb = new StringBuilder(); string contentType; //default contentType string status = "200 Success"; //default status int initialPos; long contentLength, startByte = 0; //find extension if (!exts.TryGetValue(Path.GetExtension(file.Name).ToLower(), out contentType)) { //default contentType = "application/octet-stream"; } using (Stream fs = file.OpenReadOnly()){ contentLength = fs.Length; //if client sent a range request. if (req.Headers.ContainsKey("range")) { var t = req.GetRangeHeader(fs.Length); //find range if (t == null) { string pageHTML = "<html><h1>416 REQUESTED RANGE NOT SATISFIABLE</h1></html>"; req.WriteRangeNotSatisfiableResponse(pageHTML, fs.Length.ToString()); return; } status = "206 Partial Content"; startByte = t.Item1; //start offset byte contentLength = (t.Item2 - t.Item1) + 1; //because contentLength is the length, not last byte. } sb.Append("HTTP/1.1 " + status + "\r\n"); sb.Append("Content-Length: " + contentLength + "\r\n"); sb.Append("Content-Type: " + contentType + "\r\n"); //we need this so that the file downloads, instead //of trying to switch views. /*sb.Append("Content-Disposition: attachment; filename=\"" + * file.Name + "\"\r\n");*/ sb.Append("\r\n"); initialPos = sb.Length; ASCIIEncoding.ASCII.GetBytes(sb.ToString()).CopyTo(buffer, 0); if (req.Headers.ContainsKey("range")) { int totalBytesRead; int bytesRead = 0; //seek to startbyte. fs.Seek(startByte, SeekOrigin.Begin); //our initial read has to be the smaller of one of these 2. int initialRead = ((buffer.Length - initialPos) < contentLength) ? buffer.Length - initialPos : (int)contentLength; // if (buffer.Length - initialPos) >= cL totalBytesRead = fs.Read(buffer, initialPos, initialRead); //Console.WriteLine(ASCIIEncoding.ASCII.GetString(buffer)); //has to be what we had initially plus what we just read. req.WriteResponse(buffer, initialPos + initialRead); Array.Clear(buffer, 0, buffer.Length); //if we still have not read up to content length, keep reading. if (totalBytesRead < contentLength) { int subsequentRead = (buffer.Length < contentLength) ? buffer.Length : (int)contentLength; // if (buffer.Length - initialPos) >= cL //keep track of previous total bytes int prevTotalBytesRead = totalBytesRead; while ((bytesRead = fs.Read(buffer, 0, subsequentRead)) != 0 && (totalBytesRead += bytesRead) < contentLength) { prevTotalBytesRead = totalBytesRead; req.WriteResponse(buffer, bytesRead); Array.Clear(buffer, 0, buffer.Length); } if (totalBytesRead >= contentLength) { //we subtract the value of totalBytes right before it was more than contentLength, //from content length (contentLength - prevTotalBytesRead) //this gives us the last bit we need to write to achieve the range requested's length. req.WriteResponse(buffer, (int)contentLength - prevTotalBytesRead); } } } else { fs.Read(buffer, initialPos, buffer.Length - initialPos); req.WriteResponse(buffer); while (fs.Read(buffer, 0, buffer.Length) != 0) { req.WriteResponse(buffer); Array.Clear(buffer, 0, buffer.Length); } } req.CloseResponse(); } }