Ejemplo n.º 1
0
        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();
            }
        }