public async Task <FileOperationResult> CopyFileAsync(MediaFileInfo mediaFile, string destinationFileName, DuplicateFileHandling dupeFileHandling = DuplicateFileHandling.ThrowError) { Guard.NotNull(mediaFile, nameof(mediaFile)); Guard.NotEmpty(destinationFileName, nameof(destinationFileName)); var destPathData = CreateDestinationPathData(mediaFile.File, destinationFileName); var destFileName = destPathData.FileName; var destFolderId = destPathData.Folder.Id; var dupe = mediaFile.FolderId == destPathData.Folder.Id // Source folder equals dest folder, so same file ? mediaFile.File // Another dest folder, check for duplicate by file name : await _db.MediaFiles.FirstOrDefaultAsync(x => x.Name == destFileName && x.FolderId == destFolderId); var copyResult = await InternalCopyFile( mediaFile.File, destPathData, true /* copyData */, (DuplicateEntryHandling)((int)dupeFileHandling), () => Task.FromResult(dupe), p => CheckUniqueFileName(p)); return(new FileOperationResult { Operation = "copy", DuplicateFileHandling = dupeFileHandling, SourceFile = mediaFile, DestinationFile = ConvertMediaFile(copyResult.Copy, destPathData.Folder), IsDuplicate = copyResult.IsDupe, UniquePath = copyResult.IsDupe ? destPathData.FullPath : null }); }
protected MediaFileInfo ConvertMediaFile(MediaFile file, MediaFolderNode folder) { var mediaFile = new MediaFileInfo(file, _storageProvider, _urlGenerator, folder?.Path) { ThumbSize = _mediaSettings.ProductThumbPictureSize }; return(mediaFile); }
public static string GetUrl(this IMediaService service, MediaFileInfo file, int thumbnailSize, string host = null, bool doFallback = true) { ProcessImageQuery query = thumbnailSize > 0 ? new ProcessImageQuery { MaxSize = thumbnailSize } : null; return(service.GetUrl(file, query, host, doFallback)); }
public async Task Invoke(HttpContext context, IMediaService mediaService, IMediaUrlGenerator mediaUrlGenerator) { var path = context.GetRouteValueAs <string>("path"); if (path.IsEmpty()) { // Cannot operate without path context.Response.ContentType = "text/html"; context.Response.StatusCode = 404; await context.Response.WriteAsync("404: Not Found"); return; } var mediaFileId = context.GetRouteValueAs <int?>("id"); MediaFileInfo mediaFile = null; if (mediaFileId.HasValue) { /// Redirect legacy URL "/{pub}/image/234/file.png" to "/{pub}/234/catalog/path/to/file.png" mediaFile = await mediaService.GetFileByIdAsync(mediaFileId.Value, MediaLoadFlags.AsNoTracking); } else { // Redirect legacy URL "/{tenant?}/uploaded/some/file.png" to "/file/1234/some/file.png" mediaFile = await mediaService.GetFileByPathAsync( SystemAlbumProvider.Files + "/" + path, MediaLoadFlags.AsNoTracking); } var url = mediaUrlGenerator.GenerateUrl(mediaFile, context.Request.QueryString, string.Empty, false); if (url.IsEmpty()) { // Cannot redirect, return 404 context.Response.ContentType = mediaFile?.MimeType ?? "text/html"; context.Response.StatusCode = 404; await context.Response.WriteAsync("404: Not Found"); } else { // Redirect to new location context.Response.StatusCode = context.Connection.IsLocal() ? 302 : 301; context.Response.Headers[HeaderNames.Location] = path; } }
public virtual string GenerateUrl( MediaFileInfo file, QueryString query = default, string host = null, bool doFallback = true) { string path; // Build virtual path with pattern "media/{id}/{album}/{dir}/{NameWithExt}" if (file?.Path != null) { path = _processedImagesRootPath + file.Id.ToString(CultureInfo.InvariantCulture) + "/" + file.Path; } else if (doFallback) { path = _processedImagesRootPath + "0/" + _fallbackImageFileName; } else { return(null); } if (host == null) { host = _host; } else if (host == string.Empty) { host = _pathBase; } else { host = host.EnsureEndsWith('/'); } var url = host; // Strip leading "/", the host/pathBase has this already if (path[0] == '/') { path = path[1..];
public string GetUrl(MediaFileInfo file, ProcessImageQuery imageQuery, string host = null, bool doFallback = true) { return(_urlGenerator.GenerateUrl(file, imageQuery, host, doFallback)); }
public async Task Invoke( HttpContext context, IMediaService mediaService, IFolderService folderService, IPermissionService permissionService, IWorkContext workContext, MediaSettings mediaSettings, MediaHelper mediaHelper, Lazy <IEnumerable <IMediaHandler> > mediaHandlers, ILogger <MediaMiddleware> logger) { var mediaFileId = context.GetRouteValueAs <int>("id"); var path = context.GetRouteValueAs <string>("path"); if (context.Request.Method != HttpMethods.Get && context.Request.Method != HttpMethods.Head) { await NotFound(null); return; } var method = context.Request.Method; MediaFileInfo mediaFile = null; MediaPathData pathData = null; if (mediaFileId == 0) { // This is most likely a request for a default placeholder image pathData = new MediaPathData(path); } else if (!mediaHelper.TokenizePath(path, false, out pathData)) { // Missing or malformed Uri: get file metadata from DB by id, but only when current user has media manage rights if (!(await permissionService.AuthorizeAsync(Permissions.Media.Update))) { await NotFound(null); return; } mediaFile = await mediaService.GetFileByIdAsync(mediaFileId, MediaLoadFlags.AsNoTracking); if (mediaFile == null || mediaFile.FolderId == null || mediaFile.Deleted) { await NotFound(mediaFile?.MimeType); return; } pathData = new MediaPathData(folderService.GetNodeById(mediaFile.FolderId.Value), mediaFile.Name) { Extension = mediaFile.Extension, MimeType = mediaFile.MimeType }; } var q = await CreateImageQuery(context, pathData.MimeType, pathData.Extension); // Security: check allowed thumnail sizes and return 404 if disallowed. var thumbMaxWidth = q.MaxWidth; var thumbMaxHeight = q.MaxHeight; var thumbSizeAllowed = IsThumbnailSizeAllowed(thumbMaxWidth) && (thumbMaxHeight == thumbMaxWidth || IsThumbnailSizeAllowed(thumbMaxHeight)); if (!thumbSizeAllowed) { await NotFound(pathData.MimeType); return; } // Create the handler context var handlerContext = new MediaHandlerContext { HttpContext = context, CurrentCustomer = workContext.CurrentCustomer, PermissionService = permissionService, MediaFileId = mediaFileId, RawPath = path, MediaService = mediaService, PathData = pathData, ImageQuery = q }; handlerContext.SetSourceFile(mediaFile); var handlers = mediaHandlers.Value.OrderBy(x => x.Order).ToArray(); // Run every registered media handler to obtain a thumbnail for the requested media file IMediaHandler currentHandler; for (var i = 0; i < handlers.Length; i++) { currentHandler = handlers[i]; // Execute handler await currentHandler.ExecuteAsync(handlerContext); if (handlerContext.Exception != null) { var isThumbExtractFail = handlerContext.Exception is ExtractThumbnailException; var statusCode = isThumbExtractFail ? StatusCodes.Status204NoContent : StatusCodes.Status500InternalServerError; var statusMessage = isThumbExtractFail ? handlerContext.Exception.InnerException?.Message.EmptyNull() : handlerContext.Exception.Message; await SendStatus(statusCode, statusMessage); return; } if (handlerContext.Executed || handlerContext.ResultFile != null) { // Get out if the handler produced a result file or has been executed in any way break; } } try { var responseFile = handlerContext.ResultFile ?? await handlerContext.GetSourceFileAsync(); if (responseFile == null || !responseFile.Exists) { await NotFound(pathData.MimeType); return; } if (string.Equals(responseFile.Extension, "." + pathData.Extension, StringComparison.CurrentCultureIgnoreCase)) { pathData.MimeType = MimeTypes.MapNameToMimeType(responseFile.Extension); } // Create FileStreamResult object var fileResult = CreateFileResult(responseFile, pathData); // Cache control ApplyResponseCaching(context, mediaSettings); // INFO: Although we are outside of the MVC pipeline we gonna use ActionContext anyway, because "FileStreamResult" // does everything we need (ByteRange, ETag etc.), so wo we gonna use it instead of reinventing the wheel. // A look at the MVC source code reveals that HttpContext is the only property that gets accessed, therefore we can omit // all the other stuff like ActionDescriptor or ModelState (which we cannot access or create from a middleware anyway). await fileResult.ExecuteResultAsync(new ActionContext { HttpContext = context, RouteData = context.GetRouteData() }); } finally { var imageProcessor = context.RequestServices.GetRequiredService <IImageProcessor>(); logger.Debug("ImageProcessor TOTAL: {0} ms.", imageProcessor.TotalProcessingTimeMs); } #region Functions bool IsThumbnailSizeAllowed(int?size) { return(size.GetValueOrDefault() == 0 || mediaSettings.IsAllowedThumbnailSize(size.Value) || permissionService.Authorize(Permissions.Media.Update, workContext.CurrentCustomer)); } async Task NotFound(string mime) { context.Response.ContentType = mime.NullEmpty() ?? "text/html"; context.Response.StatusCode = 404; await context.Response.WriteAsync("404: Not Found"); } async Task SendStatus(int code, string message) { context.Response.StatusCode = code; await context.Response.WriteAsync(message); } #endregion }
public static string Media(this IUrlHelper urlHelper, MediaFileInfo file, ProcessImageQuery query, string host = null, bool doFallback = true) { var mediaService = urlHelper.ActionContext.HttpContext.RequestServices.GetRequiredService <IMediaService>(); return(mediaService.GetUrl(file, query, host, doFallback)); }
public static string Media(this IUrlHelper urlHelper, MediaFileInfo file, int thumbnailSize = 0, string host = null, bool doFallback = true) { var mediaService = urlHelper.ActionContext.HttpContext.RequestServices.GetRequiredService <IMediaService>(); return(mediaService.GetUrl(file, thumbnailSize, host, doFallback)); }
public DuplicateMediaFileException(string message, MediaFileInfo dupeFile, string uniquePath) : base(message) { File = dupeFile; UniquePath = uniquePath; }
public InvalidOperationException IdenticalPaths(MediaFileInfo file) { Guard.NotNull(file, nameof(file)); return(new InvalidOperationException(T("Admin.Media.Exception.FileNamesIdentical", file.Path))); }
public DuplicateMediaFileException DuplicateFile(string fullPath, MediaFileInfo dupeFile, string uniquePath) { return(new DuplicateMediaFileException(T("Admin.Media.Exception.DuplicateFile", fullPath), dupeFile, uniquePath)); }