Exemple #1
0
        /// <summary>
        /// Processes the binary file request.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ProcessBinaryFileRequest( HttpContext context )
        {
            int fileId = context.Request.QueryString["id"].AsInteger() ?? 0;
            Guid fileGuid = context.Request.QueryString["guid"].AsGuid();

            if ( fileId == 0 && fileGuid.Equals( Guid.Empty ) )
            {
                SendNotFound( context );
            }

            var binaryFileQuery = new BinaryFileService().Queryable();
            if ( fileGuid != Guid.Empty )
            {
                binaryFileQuery = binaryFileQuery.Where( a => a.Guid == fileGuid );
            }
            else
            {
                binaryFileQuery = binaryFileQuery.Where( a => a.Id == fileId );
            }

            //// get just the binaryFileMetaData (not the file content) just in case we can get the filecontent faster from the cache
            //// a null LastModifiedDateTime shouldn't happen, but just in case, set it to DateTime.MaxValue so we error on the side of not getting it from the cache
            var binaryFileMetaData = binaryFileQuery.Select( a => new
            {
                BinaryFileType_AllowCaching = a.BinaryFileType.AllowCaching,
                LastModifiedDateTime = a.LastModifiedDateTime ?? DateTime.MaxValue,
                a.MimeType,
                a.FileName
            } ).FirstOrDefault();

            if ( binaryFileMetaData == null )
            {
                SendNotFound( context );
                return;
            }

            byte[] fileContent = null;

            // Is it cached
            string cacheName = Uri.EscapeDataString( context.Request.Url.Query );
            string physCachedFilePath = context.Request.MapPath( string.Format( "~/App_Data/Cache/{0}", cacheName ) );
            if ( binaryFileMetaData.BinaryFileType_AllowCaching && File.Exists( physCachedFilePath ) )
            {
                // Has the file been modified since the last cached datetime?
                DateTime cachedFileDateTime = File.GetCreationTime( physCachedFilePath );
                if ( binaryFileMetaData.LastModifiedDateTime < cachedFileDateTime )
                {
                    // NOTE: the cached file has already been resized (the size is part of the cached file's filename), so we don't need to resize it again
                    fileContent = FetchFromCache( physCachedFilePath );
                }
            }

            if ( fileContent == null )
            {
                // If we didn't get it from the cache, get it from the binaryFileService
                BinaryFile binaryFile = GetFromBinaryFileService( context, fileId, fileGuid );

                if ( binaryFile != null && binaryFile.Data != null )
                {
                    fileContent = binaryFile.Data.Content;
                }

                // If we got the image from the binaryFileService, it might need to be resized and cached
                if ( fileContent != null )
                {
                    // If more than 1 query string param is passed in, assume resize is needed
                    if ( context.Request.QueryString.Count > 1 )
                    {
                        // if it isn't an SVG file, do a Resize
                        if ( binaryFile.MimeType != "image/svg+xml" )
                        {
                            fileContent = GetResized( context.Request.QueryString, fileContent );
                        }
                    }

                    if ( binaryFileMetaData.BinaryFileType_AllowCaching )
                    {
                        Cache( fileContent, physCachedFilePath );
                    }
                }
            }

            if ( fileContent == null )
            {
                // if we couldn't get the file from the binaryFileServie or the cache, respond with NotFound
                SendNotFound( context );
                return;
            }

            // respond with File
            context.Response.ContentType = binaryFileMetaData.MimeType;
            context.Response.AddHeader( "content-disposition", "inline;filename=" + binaryFileMetaData.FileName );
            context.Response.BinaryWrite( fileContent );
            context.Response.Flush();
        }
        /// <summary>
        /// Processes the binary file request.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ProcessBinaryFileRequest( HttpContext context )
        {
            int fileId = context.Request.QueryString["id"].AsInteger() ?? 0;
            Guid fileGuid = context.Request.QueryString["guid"].AsGuid();

            if ( fileId == 0 && fileGuid.Equals( Guid.Empty ) )
            {
                SendNotFound( context );
            }

            var rockContext = new RockContext();

            var binaryFileQuery = new BinaryFileService( rockContext ).Queryable();
            if ( fileGuid != Guid.Empty )
            {
                binaryFileQuery = binaryFileQuery.Where( a => a.Guid == fileGuid );
            }
            else
            {
                binaryFileQuery = binaryFileQuery.Where( a => a.Id == fileId );
            }

            //// get just the binaryFileMetaData (not the file content) just in case we can get the filecontent faster from the cache
            //// a null ModifiedDateTime shouldn't happen, but just in case, set it to DateTime.MaxValue so we error on the side of not getting it from the cache
            var binaryFileMetaData = binaryFileQuery.Select( a => new
            {
                BinaryFileType_AllowCaching = a.BinaryFileType.AllowCaching,
                BinaryFileType_RequiresSecurity = a.BinaryFileType.RequiresSecurity,
                ModifiedDateTime = a.ModifiedDateTime ?? DateTime.MaxValue,
                a.MimeType,
                a.FileName
            } ).FirstOrDefault();

            if ( binaryFileMetaData == null )
            {
                SendNotFound( context );
                return;
            }

            //// if the binaryFile's BinaryFileType requires security, check security
            //// note: we put a RequiresSecurity flag on BinaryFileType because checking security for every image would be slow (~40ms+ per image request)
            if ( binaryFileMetaData.BinaryFileType_RequiresSecurity )
            {
                var currentUser = new UserLoginService( rockContext ).GetByUserName( UserLogin.GetCurrentUserName() );
                Person currentPerson = currentUser != null ? currentUser.Person : null;
                BinaryFile binaryFileAuth = new BinaryFileService( rockContext ).Queryable( "BinaryFileType" ).First( a => a.Guid == fileGuid || a.Id == fileId );
                if ( !binaryFileAuth.IsAuthorized( Authorization.VIEW, currentPerson ) )
                {
                    SendNotAuthorized( context );
                    return;
                }
            }

            byte[] fileContent = null;

            // Is it cached
            string cacheName = UrlQueryToCachedFileName( context.Request.QueryString, binaryFileMetaData.MimeType );
            string physCachedFilePath = context.Request.MapPath( string.Format( "~/App_Data/Cache/{0}", cacheName ) );
            if ( binaryFileMetaData.BinaryFileType_AllowCaching && File.Exists( physCachedFilePath ) )
            {
                //// Compare the File's Creation DateTime (which comes from the OS's clock), adjust it for the Rock OrgTimeZone, then compare to BinaryFile's ModifiedDateTime (which is already in OrgTimeZone).
                //// If the BinaryFile record in the database is less recent than the last time this was cached, it is safe to use the Cached version.
                //// NOTE: A BinaryFile record is typically just added and never modified (a modify is just creating a new BinaryFile record and deleting the old one), so the cached version will probably always be the correct choice.
                DateTime cachedFileDateTime = RockDateTime.ConvertLocalDateTimeToRockDateTime( File.GetCreationTime( physCachedFilePath ) );
                if ( binaryFileMetaData.ModifiedDateTime < cachedFileDateTime )
                {
                    // NOTE: the cached file has already been resized (the size is part of the cached file's filename), so we don't need to resize it again
                    fileContent = FetchFromCache( physCachedFilePath );
                }
            }

            if ( fileContent == null )
            {
                // If we didn't get it from the cache, get it from the binaryFileService
                BinaryFile binaryFile = GetFromBinaryFileService( context, fileId, fileGuid );

                if ( binaryFile != null && binaryFile.Data != null )
                {
                    fileContent = binaryFile.Data.Content;
                }

                // If we got the image from the binaryFileService, it might need to be resized and cached
                if ( fileContent != null )
                {
                    // If more than 1 query string param is passed in, assume resize is needed
                    if ( context.Request.QueryString.Count > 1 )
                    {
                        // if it isn't an SVG file, do a Resize
                        if ( binaryFile.MimeType != "image/svg+xml" )
                        {
                            fileContent = GetResized( context.Request.QueryString, fileContent );
                        }
                    }

                    if ( binaryFileMetaData.BinaryFileType_AllowCaching )
                    {
                        Cache( fileContent, physCachedFilePath );
                    }
                }
            }

            if ( fileContent == null )
            {
                // if we couldn't get the file from the binaryFileServie or the cache, respond with NotFound
                SendNotFound( context );
                return;
            }

            // respond with File
            context.Response.ContentType = binaryFileMetaData.MimeType;
            context.Response.AddHeader( "content-disposition", "inline;filename=" + binaryFileMetaData.FileName );
            if ( binaryFileMetaData.BinaryFileType_AllowCaching )
            {
                // if binaryFileType is set to allowcaching, also tell the browser to cache it for 365 days
                context.Response.Cache.SetLastModified( binaryFileMetaData.ModifiedDateTime );
                context.Response.Cache.SetMaxAge( new TimeSpan( 365, 0, 0, 0 ) );
            }

            context.Response.BinaryWrite( fileContent );
            context.Response.Flush();
        }