コード例 #1
0
        public void ReplyWithFileContent(string path, string originalPath = null)
        {
            //Deal with BL-3153, where the file was still open in another thread
            FileStream fs;

            if (!RobustFile.Exists(path))
            {
                //for audio, at least, this is not really an error. We constantly are asking if audio already exists for the current segment
                //enhance: maybe audio should go through a different path, e.g. "/bloom/audio/somefile.wav"
                //then this path COULD write and error
                //Logger.WriteError("Server could not find" + path);
                _actualContext.Response.StatusCode = 404;
                return;
            }

            try
            {
                fs = RobustFile.OpenRead(path);
            }
            catch (Exception error)
            {
                Logger.WriteError("Server could not read " + path, error);
                _actualContext.Response.StatusCode = 500;
                return;
            }

            using (fs)
            {
                _actualContext.Response.ContentLength64 = fs.Length;
                _actualContext.Response.AppendHeader("PathOnDisk", HttpUtility.UrlEncode(path));
                if (ShouldCache(path, originalPath))
                {
                    _actualContext.Response.AppendHeader("Cache-Control",
                                                         "max-age=600000"); // about a week...if someone spends longer editing one book, well, files will get loaded one more time...
                }

                // A HEAD request (rather than a GET or POST request) is a request for just headers, and nothing can be written
                // to the OutputStream. It is normally used to check if the contents of the file have changed without taking the
                // time and bandwidth needed to download the full contents of the file. The 2 pieces of information being returned
                // are the Content-Length and Last-Modified headers. The requestor can use this information to determine if the
                // contents of the file have changed, and if they have changed the requestor can then decide if the file needs to
                // be reloaded. It is useful when debugging with tools which automatically reload the page when something changes.
                if (_actualContext.Request.HttpMethod == "HEAD")
                {
                    var lastModified = RobustFile.GetLastWriteTimeUtc(path).ToString("R");

                    // Originally we were returning the Last-Modified header with every response, but we discovered that this was
                    // causing Geckofx to cache the contents of the files. This made debugging difficult because, even if the file
                    // changed, Geckofx would use the cached file rather than requesting the updated file from the localhost.
                    _actualContext.Response.AppendHeader("Last-Modified", lastModified);
                }
                else if (fs.Length < 2 * 1024 * 1024)
                {
                    // This buffer size was picked to be big enough for any of the standard files we load in every page.
                    // Profiling indicates it is MUCH faster to use Response.Close() rather than writing to the output stream,
                    // though the gain may be illusory since the final 'false' argument allows our code to proceed without waiting
                    // for the complete data transfer. At a minimum, it makes this thread available to work on another
                    // request sooner.
                    var buffer = new byte[fs.Length];
                    fs.Read(buffer, 0, (int)fs.Length);
                    _actualContext.Response.Close(buffer, false);
                }
                else
                {
                    // For really big (typically image) files, use the old buffered approach
                    try
                    {
                        var buffer = new byte[1024 * 512];                         //512KB
                        int read;
                        while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            _actualContext.Response.OutputStream.Write(buffer, 0, read);
                        }
                        _actualContext.Response.OutputStream.Close();
                    }
                    catch (HttpListenerException e)
                    {
                        // If the page is gone and no longer able to accept the data, just log it.
                        ReportHttpListenerProblem(e);
                    }
                }
            }

            HaveOutput = true;
        }
コード例 #2
0
        public void ReplyWithFileContent(string path)
        {
            //Deal with BL-3153, where the file was still open in another thread
            FileStream fs;

            if (!RobustFile.Exists(path))
            {
                //for audio, at least, this is not really an error. We constantly are asking if audio already exists for the current segment
                //enhance: maybe audio should go through a different path, e.g. "/bloom/audio/somefile.wav"
                //then this path COULD write and error
                //Logger.WriteError("Server could not find" + path);
                _actualContext.Response.StatusCode = 404;
                return;
            }

            try
            {
                fs = RobustFile.OpenRead(path);
            }
            catch (Exception error)
            {
                Logger.WriteError("Server could not read " + path, error);
                _actualContext.Response.StatusCode = 500;
                return;
            }

            using (fs)
            {
                _actualContext.Response.ContentLength64 = fs.Length;
                _actualContext.Response.AppendHeader("PathOnDisk", HttpUtility.UrlEncode(path));
                //helps with debugging what file is being chosen

                // A HEAD request (rather than a GET or POST request) is a request for just headers, and nothing can be written
                // to the OutputStream. It is normally used to check if the contents of the file have changed without taking the
                // time and bandwidth needed to download the full contents of the file. The 2 pieces of information being returned
                // are the Content-Length and Last-Modified headers. The requestor can use this information to determine if the
                // contents of the file have changed, and if they have changed the requestor can then decide if the file needs to
                // be reloaded. It is useful when debugging with tools which automatically reload the page when something changes.
                if (_actualContext.Request.HttpMethod == "HEAD")
                {
                    var lastModified = RobustFile.GetLastWriteTimeUtc(path).ToString("R");

                    // Originally we were returning the Last-Modified header with every response, but we discovered that this was
                    // causing Geckofx to cache the contents of the files. This made debugging difficult because, even if the file
                    // changed, Geckofx would use the cached file rather than requesting the updated file from the localhost.
                    _actualContext.Response.AppendHeader("Last-Modified", lastModified);
                }
                else
                {
                    var buffer = new byte[1024 * 512];                   //512KB
                    int read;
                    while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        _actualContext.Response.OutputStream.Write(buffer, 0, read);
                    }
                }
            }

            _actualContext.Response.OutputStream.Close();
            HaveOutput = true;
        }