/// <summary>
        /// Ensures that the image version with the given size exsists
        /// and returns its public URL.
        /// </summary>
        /// <param name="id">The unique id</param>
        /// <param name="width">The requested width</param>
        /// <param name="height">The optionally requested height</param>
        /// <returns>The public URL</returns>
        public async Task <string> EnsureVersionAsync(Guid id, int width, int?height = null)
        {
            if (_processor != null)
            {
                var media = await GetByIdAsync(id).ConfigureAwait(false);

                if (media != null)
                {
                    var query = media.Versions
                                .Where(v => v.Width == width);

                    if (height.HasValue)
                    {
                        query = query.Where(v => v.Height == height);
                    }
                    else
                    {
                        query = query.Where(v => !v.Height.HasValue);
                    }

                    var version = query.FirstOrDefault();

                    if (version == null)
                    {
                        // If the requested size is equal to the original size, return true
                        if (media.Width == width && (!height.HasValue || media.Height == height.Value))
                        {
                            return(GetPublicUrl(media));
                        }

                        // Get the image file
                        using (var stream = new MemoryStream())
                        {
                            using (var session = await _storage.OpenAsync().ConfigureAwait(false))
                            {
                                if (!await session.GetAsync(media.Id + "-" + media.Filename, stream).ConfigureAwait(false))
                                {
                                    return(null);
                                }

                                // Reset strem position
                                stream.Position = 0;

                                using (var output = new MemoryStream())
                                {
                                    if (height.HasValue)
                                    {
                                        _processor.CropScale(stream, output, width, height.Value);
                                    }
                                    else
                                    {
                                        _processor.Scale(stream, output, width);
                                    }
                                    output.Position = 0;
                                    bool upload = false;

                                    lock (ScaleMutex)
                                    {
                                        // We have to make sure we don't scale multiple files
                                        // at the same time as it can create index violations.
                                        version = query.FirstOrDefault();

                                        if (version == null)
                                        {
                                            var info = new FileInfo(media.Filename);

                                            version = new MediaVersion
                                            {
                                                Id            = Guid.NewGuid(),
                                                Size          = output.Length,
                                                Width         = width,
                                                Height        = height,
                                                FileExtension = info.Extension
                                            };
                                            media.Versions.Add(version);

                                            _repo.Save(media);
                                            RemoveFromCache(media);

                                            upload = true;
                                        }
                                    }

                                    if (upload)
                                    {
                                        return(await session.PutAsync(GetResourceName(media, width, height), media.ContentType, output)
                                               .ConfigureAwait(false));
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // If the requested size is equal to the original size, return true
                        if (media.Width == width && (!height.HasValue || media.Height == height.Value))
                        {
                            return(GetPublicUrl(media));
                        }
                        return(GetPublicUrl(media, width, height, version.FileExtension));
                    }
                }
            }
            return(null);
        }
Exemple #2
0
        public async Task <string> EnsureVersionAsync(Media media, int width, int?height = null)
        {
            // Get the media type
            var type = App.MediaTypes.GetItem(media.Filename);

            // If this type doesn't allow processing, return the original url
            if (!type.AllowProcessing)
            {
                return(GetPublicUrl(media));
            }

            // If the requested size is equal to the original size, return true
            if (media.Width == width && (!height.HasValue || media.Height == height.Value))
            {
                return(GetPublicUrl(media));
            }

            var query = media.Versions
                        .Where(v => v.Width == width);

            query = height.HasValue ? query.Where(v => v.Height == height) : query.Where(v => !v.Height.HasValue);

            var version = query.FirstOrDefault();

            if (version != null)
            {
                return(media.Width == width && (!height.HasValue || media.Height == height.Value)
                    ? GetPublicUrl(media)
                    : GetPublicUrl(media, width, height, version.FileExtension));
            }

            // Get the image file
            using (var stream = new MemoryStream())
            {
                using (var session = await _storage.OpenAsync().ConfigureAwait(false))
                {
                    if (!await session.GetAsync(media.Id + "-" + media.Filename, stream).ConfigureAwait(false))
                    {
                        return(null);
                    }

                    // Reset strem position
                    stream.Position = 0;

                    using (var output = new MemoryStream())
                    {
                        if (height.HasValue)
                        {
                            _processor.CropScale(stream, output, width, height.Value);
                        }
                        else
                        {
                            _processor.Scale(stream, output, width);
                        }
                        output.Position = 0;
                        bool upload = false;

                        lock (ScaleMutex)
                        {
                            // We have to make sure we don't scale multiple files
                            // at the same time as it can create index violations.
                            version = query.FirstOrDefault();

                            if (version == null)
                            {
                                var info = new FileInfo(media.Filename);

                                version = new MediaVersion
                                {
                                    Id            = Guid.NewGuid(),
                                    Size          = output.Length,
                                    Width         = width,
                                    Height        = height,
                                    FileExtension = info.Extension
                                };
                                media.Versions.Add(version);

                                _repo.Save(media).Wait();
                                RemoveFromCache(media);

                                upload = true;
                            }
                        }

                        if (upload)
                        {
                            return(await session.PutAsync(GetResourceName(media, width, height), media.ContentType,
                                                          output)
                                   .ConfigureAwait(false));
                        }
                        //When moving this out of its parent method, realized that if the mutex failed, it would just fall back to the null instead of trying to return the issue.
                        //Added this to ensure that queries didn't just give up if they weren't the first to the party.
                        return(GetPublicUrl(media, width, height, version.FileExtension));
                    }
                }
            }
            // If the requested size is equal to the original size, return true
        }
        /// <summary>
        /// Ensures that the image version with the given size exsists
        /// and returns its public URL.
        /// </summary>
        /// <param name="id">The unique id</param>
        /// <param name="width">The requested width</param>
        /// <param name="height">The optionally requested height</param>
        /// <returns>The public URL</returns>
        public async Task <string> EnsureVersionAsync(Guid id, int width, int?height = null)
        {
            if (processor != null)
            {
                var query = db.MediaVersions
                            .Where(v => v.MediaId == id && v.Width == width);

                if (height.HasValue)
                {
                    query = query.Where(v => v.Height == height);
                }
                else
                {
                    query = query.Where(v => !v.Height.HasValue);
                }

                var version = query.FirstOrDefault();

                if (version == null)
                {
                    var media = db.Media
                                .FirstOrDefault(m => m.Id == id);

                    // If the media is missing return false
                    if (media == null)
                    {
                        return(null);
                    }

                    // If the requested size is equal to the original size, return true
                    if (media.Width == width && (!height.HasValue || media.Height == height.Value))
                    {
                        return(GetPublicUrl(media));
                    }

                    // Get the image file
                    using (var stream = new MemoryStream()) {
                        using (var session = await storage.OpenAsync()) {
                            if (!await session.GetAsync(media.Id + "-" + media.Filename, stream))
                            {
                                return(null);
                            }

                            // Reset strem position
                            stream.Position = 0;

                            using (var output = new MemoryStream()) {
                                if (height.HasValue)
                                {
                                    processor.CropScale(stream, output, width, height.Value);
                                }
                                else
                                {
                                    processor.Scale(stream, output, width);
                                }
                                output.Position = 0;
                                bool upload = false;

                                lock (scalemutex) {
                                    // We have to make sure we don't scale multiple files
                                    // at the same time as it can create index violations.
                                    version = query.FirstOrDefault();

                                    if (version == null)
                                    {
                                        version = new MediaVersion()
                                        {
                                            Id      = Guid.NewGuid(),
                                            MediaId = media.Id,
                                            Size    = output.Length,
                                            Width   = width,
                                            Height  = height
                                        };
                                        db.MediaVersions.Add(version);
                                        db.SaveChanges();

                                        upload = true;
                                    }
                                }

                                if (upload)
                                {
                                    return(await session.PutAsync(GetResourceName(media, width, height, ".jpg"), "image/jpeg", output));
                                }
                            }
                        }
                    }
                }
                else
                {
                    var media = db.Media
                                .FirstOrDefault(m => m.Id == id);

                    // If the media is missing return false
                    if (media == null)
                    {
                        return(null);
                    }

                    // If the requested size is equal to the original size, return true
                    if (media.Width == width && (!height.HasValue || media.Height == height.Value))
                    {
                        return(GetPublicUrl(media));
                    }
                    return(GetPublicUrl(media, width, height, ".jpg"));
                }
            }
            return(null);
        }