private void RespondWithFile(File422 file, WebRequest req) { Stream fs = file.OpenReadOnly(); if (req.Headers.ContainsKey("range")) { WriteWithRangeHeader(file, fs, req); return; } // Send response code and headers string response = "HTTP/1.1 200 OK\r\n" + "Content-Length: " + fs.Length + "\r\n" + "Content-Type: " + file.GetContentType() + "\r\n\r\n"; byte[] responseBytes = Encoding.ASCII.GetBytes(response); req.WriteResponse(responseBytes, 0, responseBytes.Length); while (true) { byte[] buf = new byte[4096]; int read = fs.Read(buf, 0, buf.Length); if (read == 0) { break; } req.WriteResponse(buf, 0, read); } fs.Close(); }
/// <summary> /// Writes the with range header. /// </summary> private void WriteWithRangeHeader(File422 file, Stream fs, WebRequest req) { String[] ranges = req.Headers["range"].Trim().Substring("byte= ".Length).Split('-'); long from; Int64.TryParse(ranges[0], out from); if (fs.Length <= from) { string invalid = "HTTP/1.1 416 Requested Range Not Satisfiable\r\n\r\n"; byte[] invalidResponseBytes = Encoding.ASCII.GetBytes(invalid); req.WriteResponse(invalidResponseBytes, 0, invalidResponseBytes.Length); } long to; if (ranges[1] != string.Empty) { Int64.TryParse(ranges[1], out to); } else { to = fs.Length - 1; } // Send response code and headers string response = "HTTP/1.1 206 Partial content\r\n" + "Content-Range: bytes " + from.ToString() + "-" + to.ToString() + "/" + fs.Length.ToString() + "\r\n" + "Content-Length: " + (to + 1 - from).ToString() + "\r\n" + "Content-Type: " + file.GetContentType() + "\r\n\r\n"; byte[] responseBytes = Encoding.ASCII.GetBytes(response); req.WriteResponse(responseBytes, 0, responseBytes.Length); fs.Seek(from, SeekOrigin.Begin); while (true) { byte[] buf = new byte[4096]; int read = 0; read = fs.Read(buf, 0, buf.Length); if (read == 0) { break; } req.WriteResponse(buf, 0, read); if (fs.Position >= to) { break; } } fs.Close(); }
private void PUTHandler(WebRequest req, string name, Dir422 dir) { if (dir.ContainsFile(name, false) || name.Contains("\\") || name.Contains("/")) { string bodyMessage = "Invalid: File already exists or filename is invalid"; string template = "HTTP/1.1 400 Bad Request\r\n" + "Content-Type: text/html\r\n" + "Content-Length: {0}\r\n\r\n" + "{1}"; string response = string.Format(template, Encoding.ASCII.GetBytes(bodyMessage).Length, bodyMessage); byte[] responseBytes = Encoding.ASCII.GetBytes(response); req.WriteResponse(responseBytes, 0, responseBytes.Length); return; } File422 file = dir.CreateFile(name); FileStream fs = (FileStream)file.OpenReadWrite(); long fileSize = 0; Int64.TryParse(req.BodySize, out fileSize); int totalread = 0; while (true) { byte[] buf = new byte[4096]; int read = req.Body.Read(buf, 0, buf.Length); fs.Write(buf, 0, read); totalread += read; if ((read == 0) || read < buf.Length && totalread >= fileSize) { break; } } fs.Dispose(); fs.Close(); req.WriteHTMLResponse("Successfully uploaded file: " + name); }
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(); } }
void SendFileRange(File422 file, long start, long end, long chunkSize, WebRequest req) { if (end < start) { throw new ArgumentException("Invalid start and end range"); } var fileStream = file.OpenReadOnly(); long fileSize = fileStream.Length; if (start > end) { req.WriteNotFoundResponse("Invalid Range Header Specified"); } if (end == 0) { end = fileSize; } req.Headers = new System.Collections.Concurrent.ConcurrentDictionary <string, string> (); if (end - start + 1 < chunkSize) { // only need to send 1 response string contentType = GetContentType(file.Name); if (contentType != null) { req.Headers ["Content-Type"] = contentType; } else { req.Headers ["Content-Type"] = "text/plain"; } var fileContents = GetFileRange(fileStream, start, end); req.WriteResponse("206 Partial Content", fileContents); } else { // need to send multiple responses string boundary = "5187ab27335732"; string contentType = GetContentType(file.Name); if (contentType != null) { req.Headers ["Content-Type"] = contentType; } long offset = start; long sent = 0; req.Headers ["Accept-Ranges"] = "bytes"; long sizeToSend = end - start + 1; while (sent <= sizeToSend) { long currentSize = (sizeToSend - sent) < chunkSize ? sizeToSend - sent: chunkSize; if (offset + currentSize > fileSize) { currentSize = fileSize - offset + 1; } if (currentSize <= 0) { break; } //Console.WriteLine ("Getting file range [{0}, {1}]", offset, offset + currentSize); var fileContents = GetFileRange(fileStream, offset, offset + currentSize); req.Headers ["Content-Range"] = String.Format("bytes {0}-{1}/{2}", offset, currentSize + offset, sizeToSend); req.WriteResponse("206 PartialContent", fileContents); offset += currentSize + 1; sent += currentSize; } } }