* prototype drag and drop upload * Add upload image endpoint * Add MediaPickerThreeController.cs * Revert "Add upload image endpoint" This reverts commit 4bb5865480737a00b723968e3bbba317b252acf7. * Update IIOHelper dependency * show preview when uploading a new media item * open uploaded media in media entry editor * map data from uploaded media entry to support cropper * add crop data to uploaded media item * remove media library buttons for media entries not created in the media library * Implement temp images save & add to media picker 3 * Implement ITemporaryImageService * Remove save logic from MediaPicker3PropertyEditor * Dont use a TempImageDto * Add GetByAlias endpoint * Add additonal xml doc * Refactor to take array of aliases * Add FromQuery attribute * Formatting * add resource to get media types by alias * validate file size and file type based on server variables * Update OpenApi.json Add media picker three to BackOfficeServerVariables * rename endpoint to upload media * Use baseurl Method * Dont upload in rte folder * pass params correctly to end point * queue files before uploading * handle invalid files * progress bar design adjustments * only create data url for images * disable edit and name buttons when uploading * fix missing error messages for invalid files * add temp location to media entry * Add startNode to TemporaryImageService.cs * Refactor get by alias * Rename to GetAllFiltered * use getAllFiltered method * remove autoselect option * fix missing alias when selecting media type * fix file filter * don't overwrite invalid entries from dropping new files * add disallowed files to filter * remove console.log * move media uploader logic to reusable function * fix missing tmp location * attach media type alias to the mediaEntry * support readonly mode * show discard changes when files has been dropped * add disabled prop to button group * emit events when upload queue starts and ends * pass node to media picker property editor * add service to keep track of all uploads in progress * add upload in progress to uploadTracker when the queue starts and ends * disabled buttons when any upload is in progress * return a subscription to align with eventsService * Fix up cases where StartNodeId was null * scope css * Show filename in dialog for selecting media type * reuse translation from media library dropzone * Don't check for only images * Remove composer * Add mediaTypeAlias to TemporaryImageService * Rename ITemporaryImageService to ITemporaryMediaService * prefix client side only props with $ so we don't send unnecessary data to the server * use prefixed dataURL in media entry editor * render icon for non images * fix auto select media type Co-authored-by: Zeegaan <nge@umbraco.dk> Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>
114 lines
4.2 KiB
C#
114 lines
4.2 KiB
C#
using System.Net;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using Umbraco.Cms.Core;
|
|
using Umbraco.Cms.Core.Configuration.Models;
|
|
using Umbraco.Cms.Core.Dictionary;
|
|
using Umbraco.Cms.Core.Events;
|
|
using Umbraco.Cms.Core.Hosting;
|
|
using Umbraco.Cms.Core.IO;
|
|
using Umbraco.Cms.Core.Media;
|
|
using Umbraco.Cms.Core.Serialization;
|
|
using Umbraco.Cms.Core.Services;
|
|
using Umbraco.Cms.Core.Strings;
|
|
using Umbraco.Cms.Web.Common.ActionsResults;
|
|
using Umbraco.Cms.Web.Common.Attributes;
|
|
using Umbraco.Cms.Web.Common.Authorization;
|
|
using Umbraco.Extensions;
|
|
|
|
namespace Umbraco.Cms.Web.BackOffice.Controllers;
|
|
|
|
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
|
[Authorize(Policy = AuthorizationPolicies.SectionAccessMedia)]
|
|
public class MediaPickerThreeController : ContentControllerBase
|
|
{
|
|
private readonly IHostingEnvironment _hostingEnvironment;
|
|
private readonly ContentSettings _contentSettings;
|
|
private readonly IImageUrlGenerator _imageUrlGenerator;
|
|
private readonly IIOHelper _ioHelper;
|
|
|
|
public MediaPickerThreeController(
|
|
ICultureDictionary cultureDictionary,
|
|
ILoggerFactory loggerFactory,
|
|
IShortStringHelper shortStringHelper,
|
|
IEventMessagesFactory eventMessages,
|
|
ILocalizedTextService localizedTextService,
|
|
IJsonSerializer serializer,
|
|
IHostingEnvironment hostingEnvironment,
|
|
IOptionsSnapshot<ContentSettings> contentSettings,
|
|
IImageUrlGenerator imageUrlGenerator,
|
|
IIOHelper ioHelper)
|
|
: base(cultureDictionary, loggerFactory, shortStringHelper, eventMessages, localizedTextService, serializer)
|
|
{
|
|
_hostingEnvironment = hostingEnvironment;
|
|
_contentSettings = contentSettings.Value;
|
|
_imageUrlGenerator = imageUrlGenerator;
|
|
_ioHelper = ioHelper;
|
|
}
|
|
|
|
[HttpPost]
|
|
public async Task<IActionResult> UploadMedia(List<IFormFile> file)
|
|
{
|
|
// Create an unique folder path to help with concurrent users to avoid filename clash
|
|
var imageTempPath =
|
|
_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempFileUploads + "/" + Guid.NewGuid());
|
|
|
|
// Ensure image temp path exists
|
|
if (Directory.Exists(imageTempPath) == false)
|
|
{
|
|
Directory.CreateDirectory(imageTempPath);
|
|
}
|
|
|
|
// Must have a file
|
|
if (file.Count == 0)
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
// Should only have one file
|
|
if (file.Count > 1)
|
|
{
|
|
return new UmbracoProblemResult("Only one file can be uploaded at a time", HttpStatusCode.BadRequest);
|
|
}
|
|
|
|
// Really we should only have one file per request to this endpoint
|
|
IFormFile formFile = file.First();
|
|
|
|
var fileName = formFile.FileName.Trim(new[] { '\"' }).TrimEnd();
|
|
var safeFileName = fileName.ToSafeFileName(ShortStringHelper);
|
|
var ext = safeFileName.Substring(safeFileName.LastIndexOf('.') + 1).ToLowerInvariant();
|
|
|
|
if (_contentSettings.IsFileAllowedForUpload(ext) == false)
|
|
{
|
|
// Throw some error - to say can't upload this IMG type
|
|
return new UmbracoProblemResult("This is not an image filetype extension that is approved", HttpStatusCode.BadRequest);
|
|
}
|
|
|
|
var newFilePath = imageTempPath + Path.DirectorySeparatorChar + safeFileName;
|
|
var relativeNewFilePath = GetRelativePath(newFilePath);
|
|
|
|
await using (FileStream stream = System.IO.File.Create(newFilePath))
|
|
{
|
|
await formFile.CopyToAsync(stream);
|
|
}
|
|
|
|
return Ok(new { tmpLocation = relativeNewFilePath });
|
|
}
|
|
|
|
// Use private method istead of _ioHelper.GetRelativePath as that is relative for the webroot and not the content root.
|
|
private string GetRelativePath(string path)
|
|
{
|
|
if (path.IsFullPath())
|
|
{
|
|
var rootDirectory = _hostingEnvironment.MapPathContentRoot("~");
|
|
var relativePath = _ioHelper.PathStartsWith(path, rootDirectory) ? path[rootDirectory.Length..] : path;
|
|
path = relativePath;
|
|
}
|
|
|
|
return PathUtility.EnsurePathIsApplicationRootPrefixed(path);
|
|
}
|
|
}
|