public async Task <HttpResponseMessage> PostAddFile() { if (Request.Content.IsMimeMultipartContent() == false) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } var root = IOHelper.MapPath(SystemDirectories.TempFileUploads); //ensure it exists Directory.CreateDirectory(root); var provider = new MultipartFormDataStreamProvider(root); var result = await Request.Content.ReadAsMultipartAsync(provider); //must have a file if (result.FileData.Count == 0) { return(Request.CreateResponse(HttpStatusCode.NotFound)); } //get the string json from the request string currentFolderId = result.FormData["currentFolder"]; int parentId = GetParentIdAsInt(currentFolderId, validatePermissions: true); var tempFiles = new PostedFiles(); var mediaService = Services.MediaService; //in case we pass a path with a folder in it, we will create it and upload media to it. if (result.FormData.ContainsKey("path")) { var folders = result.FormData["path"].Split(Constants.CharArrays.ForwardSlash); for (int i = 0; i < folders.Length - 1; i++) { var folderName = folders[i]; IMedia folderMediaItem; //if uploading directly to media root and not a subfolder if (parentId == -1) { //look for matching folder folderMediaItem = mediaService.GetRootMedia().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder); if (folderMediaItem == null) { //if null, create a folder folderMediaItem = mediaService.CreateMedia(folderName, -1, Constants.Conventions.MediaTypes.Folder); mediaService.Save(folderMediaItem); } } else { //get current parent var mediaRoot = mediaService.GetById(parentId); //if the media root is null, something went wrong, we'll abort if (mediaRoot == null) { return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "The folder: " + folderName + " could not be used for storing images, its ID: " + parentId + " returned null")); } //look for matching folder folderMediaItem = FindInChildren(mediaRoot.Id, folderName, Constants.Conventions.MediaTypes.Folder); if (folderMediaItem == null) { //if null, create a folder folderMediaItem = mediaService.CreateMedia(folderName, mediaRoot, Constants.Conventions.MediaTypes.Folder); mediaService.Save(folderMediaItem); } } //set the media root to the folder id so uploaded files will end there. parentId = folderMediaItem.Id; } } //get the files foreach (var file in result.FileData) { var fileName = file.Headers.ContentDisposition.FileName.Trim(Constants.CharArrays.DoubleQuote).TrimEnd(); var safeFileName = fileName.ToSafeFileName(); var ext = safeFileName.Substring(safeFileName.LastIndexOf('.') + 1).ToLower(); if (Current.Configs.Settings().Content.IsFileAllowedForUpload(ext)) { var mediaType = Constants.Conventions.MediaTypes.File; if (result.FormData["contentTypeAlias"] == Constants.Conventions.MediaTypes.AutoSelect) { if (Current.Configs.Settings().Content.ImageFileTypes.Contains(ext)) { mediaType = Constants.Conventions.MediaTypes.Image; } } else { mediaType = result.FormData["contentTypeAlias"]; } var mediaItemName = fileName.ToFriendlyName(); var f = mediaService.CreateMedia(mediaItemName, parentId, mediaType, Security.CurrentUser.Id); var fileInfo = new FileInfo(file.LocalFileName); var fs = fileInfo.OpenReadWithRetry(); if (fs == null) { throw new InvalidOperationException("Could not acquire file stream"); } using (fs) { f.SetValue(Services.ContentTypeBaseServices, Constants.Conventions.Media.File, fileName, fs); } var saveResult = mediaService.Save(f, Security.CurrentUser.Id); if (saveResult == false) { AddCancelMessage(tempFiles, message: Services.TextService.Localize("speechBubbles/operationCancelledText") + " -- " + mediaItemName); } else { tempFiles.UploadedFiles.Add(new ContentPropertyFile { FileName = fileName, PropertyAlias = Constants.Conventions.Media.File, TempFilePath = file.LocalFileName }); } } else { tempFiles.Notifications.Add(new Notification( Services.TextService.Localize("speechBubbles/operationFailedHeader"), Services.TextService.Localize("media/disallowedFileType"), NotificationStyle.Warning)); } } //Different response if this is a 'blueimp' request if (Request.GetQueryNameValuePairs().Any(x => x.Key == "origin")) { var origin = Request.GetQueryNameValuePairs().First(x => x.Key == "origin"); if (origin.Value == "blueimp") { return(Request.CreateResponse(HttpStatusCode.OK, tempFiles, //Don't output the angular xsrf stuff, blue imp doesn't like that new JsonMediaTypeFormatter())); } } return(Request.CreateResponse(HttpStatusCode.OK, tempFiles)); }
/// <summary> /// Used to submit a media file /// </summary> /// <returns></returns> /// <remarks> /// We cannot validate this request with attributes (nicely) due to the nature of the multi-part for data. /// </remarks> public async Task <IActionResult> PostAddFile([FromForm] string path, [FromForm] string currentFolder, [FromForm] string contentTypeAlias, List <IFormFile> file) { var root = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempFileUploads); //ensure it exists Directory.CreateDirectory(root); //must have a file if (file.Count == 0) { return(NotFound()); } //get the string json from the request var parentIdResult = await GetParentIdAsIntAsync(currentFolder, validatePermissions : true); if (!(parentIdResult.Result is null)) { return(parentIdResult.Result); } var parentId = parentIdResult.Value; if (!parentId.HasValue) { return(NotFound("The passed id doesn't exist")); } var tempFiles = new PostedFiles(); //in case we pass a path with a folder in it, we will create it and upload media to it. if (!string.IsNullOrEmpty(path)) { if (!IsFolderCreationAllowedHere(parentId.Value)) { AddCancelMessage(tempFiles, _localizedTextService.Localize("speechBubbles", "folderUploadNotAllowed")); return(Ok(tempFiles)); } var folders = path.Split(Constants.CharArrays.ForwardSlash); for (int i = 0; i < folders.Length - 1; i++) { var folderName = folders[i]; IMedia folderMediaItem; //if uploading directly to media root and not a subfolder if (parentId == Constants.System.Root) { //look for matching folder folderMediaItem = _mediaService.GetRootMedia().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder); if (folderMediaItem == null) { //if null, create a folder folderMediaItem = _mediaService.CreateMedia(folderName, -1, Constants.Conventions.MediaTypes.Folder); _mediaService.Save(folderMediaItem); } } else { //get current parent var mediaRoot = _mediaService.GetById(parentId.Value); //if the media root is null, something went wrong, we'll abort if (mediaRoot == null) { return(Problem( "The folder: " + folderName + " could not be used for storing images, its ID: " + parentId + " returned null")); } //look for matching folder folderMediaItem = FindInChildren(mediaRoot.Id, folderName, Constants.Conventions.MediaTypes.Folder); if (folderMediaItem == null) { //if null, create a folder folderMediaItem = _mediaService.CreateMedia(folderName, mediaRoot, Constants.Conventions.MediaTypes.Folder); _mediaService.Save(folderMediaItem); } } //set the media root to the folder id so uploaded files will end there. parentId = folderMediaItem.Id; } } var mediaTypeAlias = string.Empty; var allMediaTypes = _mediaTypeService.GetAll().ToList(); var allowedContentTypes = new HashSet <IMediaType>(); if (parentId != Constants.System.Root) { var mediaFolderItem = _mediaService.GetById(parentId.Value); var mediaFolderType = allMediaTypes.FirstOrDefault(x => x.Alias == mediaFolderItem.ContentType.Alias); if (mediaFolderType != null) { IMediaType mediaTypeItem = null; foreach (ContentTypeSort allowedContentType in mediaFolderType.AllowedContentTypes) { IMediaType checkMediaTypeItem = allMediaTypes.FirstOrDefault(x => x.Id == allowedContentType.Id.Value); allowedContentTypes.Add(checkMediaTypeItem); var fileProperty = checkMediaTypeItem?.CompositionPropertyTypes.FirstOrDefault(x => x.Alias == Constants.Conventions.Media.File); if (fileProperty != null) { mediaTypeItem = checkMediaTypeItem; } } //Only set the permission-based mediaType if we only allow 1 specific file under this parent. if (allowedContentTypes.Count == 1 && mediaTypeItem != null) { mediaTypeAlias = mediaTypeItem.Alias; } } } else { var typesAllowedAtRoot = allMediaTypes.Where(x => x.AllowedAsRoot).ToList(); allowedContentTypes.UnionWith(typesAllowedAtRoot); } //get the files foreach (var formFile in file) { var fileName = formFile.FileName.Trim(Constants.CharArrays.DoubleQuote).TrimEnd(); var safeFileName = fileName.ToSafeFileName(ShortStringHelper); var ext = safeFileName.Substring(safeFileName.LastIndexOf('.') + 1).ToLower(); if (!_contentSettings.IsFileAllowedForUpload(ext)) { tempFiles.Notifications.Add(new BackOfficeNotification( _localizedTextService.Localize("speechBubbles", "operationFailedHeader"), _localizedTextService.Localize("media", "disallowedFileType"), NotificationStyle.Warning)); continue; } if (string.IsNullOrEmpty(mediaTypeAlias)) { mediaTypeAlias = Constants.Conventions.MediaTypes.File; if (contentTypeAlias == Constants.Conventions.MediaTypes.AutoSelect) { // Look up MediaTypes foreach (var mediaTypeItem in allMediaTypes) { var fileProperty = mediaTypeItem.CompositionPropertyTypes.FirstOrDefault(x => x.Alias == Constants.Conventions.Media.File); if (fileProperty == null) { continue; } var dataTypeKey = fileProperty.DataTypeKey; var dataType = _dataTypeService.GetDataType(dataTypeKey); if (dataType == null || dataType.Configuration is not IFileExtensionsConfig fileExtensionsConfig) { continue; } var fileExtensions = fileExtensionsConfig.FileExtensions; if (fileExtensions == null || fileExtensions.All(x => x.Value != ext)) { continue; } mediaTypeAlias = mediaTypeItem.Alias; break; } // If media type is still File then let's check if it's an image. if (mediaTypeAlias == Constants.Conventions.MediaTypes.File && _imageUrlGenerator.SupportedImageFileTypes.Contains(ext)) { mediaTypeAlias = Constants.Conventions.MediaTypes.Image; } } else { mediaTypeAlias = contentTypeAlias; } } if (allowedContentTypes.Any(x => x.Alias == mediaTypeAlias) == false) { tempFiles.Notifications.Add(new BackOfficeNotification( _localizedTextService.Localize("speechBubbles", "operationFailedHeader"), _localizedTextService.Localize("media", "disallowedMediaType", new[] { mediaTypeAlias }), NotificationStyle.Warning)); continue; } var mediaItemName = fileName.ToFriendlyName(); var createdMediaItem = _mediaService.CreateMedia(mediaItemName, parentId.Value, mediaTypeAlias, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.Id); await using (var stream = formFile.OpenReadStream()) { createdMediaItem.SetValue(_mediaFileManager, _mediaUrlGenerators, _shortStringHelper, _contentTypeBaseServiceProvider, Constants.Conventions.Media.File, fileName, stream); } var saveResult = _mediaService.Save(createdMediaItem, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.Id); if (saveResult == false) { AddCancelMessage(tempFiles, _localizedTextService.Localize("speechBubbles", "operationCancelledText") + " -- " + mediaItemName); } } //Different response if this is a 'blueimp' request if (HttpContext.Request.Query.Any(x => x.Key == "origin")) { var origin = HttpContext.Request.Query.First(x => x.Key == "origin"); if (origin.Value == "blueimp") { return(new JsonResult(tempFiles)); //Don't output the angular xsrf stuff, blue imp doesn't like that } } return(Ok(tempFiles)); }
internal static async Task <HttpResponseMessage> PostSetAvatarInternal(HttpRequestMessage request, IUserService userService, IAppCache cache, int id) { if (request.Content.IsMimeMultipartContent() == false) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } var root = IOHelper.MapPath(SystemDirectories.TempFileUploads); //ensure it exists Directory.CreateDirectory(root); var provider = new MultipartFormDataStreamProvider(root); var result = await request.Content.ReadAsMultipartAsync(provider); //must have a file if (result.FileData.Count == 0) { return(request.CreateResponse(HttpStatusCode.NotFound)); } var user = userService.GetUserById(id); if (user == null) { return(request.CreateResponse(HttpStatusCode.NotFound)); } var tempFiles = new PostedFiles(); if (result.FileData.Count > 1) { return(request.CreateValidationErrorResponse("The request was not formatted correctly, only one file can be attached to the request")); } //get the file info var file = result.FileData[0]; var fileName = file.Headers.ContentDisposition.FileName.Trim(Constants.CharArrays.DoubleQuote).TrimEnd(); var safeFileName = fileName.ToSafeFileName(); var ext = safeFileName.Substring(safeFileName.LastIndexOf('.') + 1).ToLower(); if (Current.Configs.Settings().Content.DisallowedUploadFiles.Contains(ext) == false) { //generate a path of known data, we don't want this path to be guessable user.Avatar = "UserAvatars/" + (user.Id + safeFileName).GenerateHash <SHA1>() + "." + ext; using (var fs = System.IO.File.OpenRead(file.LocalFileName)) { Current.MediaFileSystem.AddFile(user.Avatar, fs, true); } userService.Save(user); //track the temp file so the cleanup filter removes it tempFiles.UploadedFiles.Add(new ContentPropertyFile { TempFilePath = file.LocalFileName }); } return(request.CreateResponse(HttpStatusCode.OK, user.GetUserAvatarUrls(cache))); }
public async Task <HttpResponseMessage> PostAddFile() { if (Request.Content.IsMimeMultipartContent() == false) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } var root = IOHelper.MapPath("~/App_Data/TEMP/FileUploads"); //ensure it exists Directory.CreateDirectory(root); var provider = new MultipartFormDataStreamProvider(root); var result = await Request.Content.ReadAsMultipartAsync(provider); //must have a file if (result.FileData.Count == 0) { return(Request.CreateResponse(HttpStatusCode.NotFound)); } //get the string json from the request int parentId; bool entityFound; GuidUdi parentUdi; string currentFolderId = result.FormData["currentFolder"]; // test for udi if (GuidUdi.TryParse(currentFolderId, out parentUdi)) { currentFolderId = parentUdi.Guid.ToString(); } if (int.TryParse(currentFolderId, out parentId) == false) { // if a guid then try to look up the entity Guid idGuid; if (Guid.TryParse(currentFolderId, out idGuid)) { var entity = Services.EntityService.GetByKey(idGuid); if (entity != null) { entityFound = true; parentId = entity.Id; } else { throw new EntityNotFoundException(currentFolderId, "The passed id doesn't exist"); } } else { return(Request.CreateValidationErrorResponse("The request was not formatted correctly, the currentFolder is not an integer or Guid")); } if (entityFound == false) { return(Request.CreateValidationErrorResponse("The request was not formatted correctly, the currentFolder is not an integer or Guid")); } } //ensure the user has access to this folder by parent id! if (CheckPermissions( new Dictionary <string, object>(), Security.CurrentUser, Services.MediaService, parentId) == false) { return(Request.CreateResponse( HttpStatusCode.Forbidden, new SimpleNotificationModel(new Notification( Services.TextService.Localize("speechBubbles/operationFailedHeader"), Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"), SpeechBubbleIcon.Warning)))); } var tempFiles = new PostedFiles(); var mediaService = ApplicationContext.Services.MediaService; //in case we pass a path with a folder in it, we will create it and upload media to it. if (result.FormData.ContainsKey("path")) { var folders = result.FormData["path"].Split('/'); for (int i = 0; i < folders.Length - 1; i++) { var folderName = folders[i]; IMedia folderMediaItem; //if uploading directly to media root and not a subfolder if (parentId == -1) { //look for matching folder folderMediaItem = mediaService.GetRootMedia().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder); if (folderMediaItem == null) { //if null, create a folder folderMediaItem = mediaService.CreateMedia(folderName, -1, Constants.Conventions.MediaTypes.Folder); mediaService.Save(folderMediaItem); } } else { //get current parent var mediaRoot = mediaService.GetById(parentId); //if the media root is null, something went wrong, we'll abort if (mediaRoot == null) { return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "The folder: " + folderName + " could not be used for storing images, its ID: " + parentId + " returned null")); } //look for matching folder folderMediaItem = mediaRoot.Children().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder); if (folderMediaItem == null) { //if null, create a folder folderMediaItem = mediaService.CreateMedia(folderName, mediaRoot, Constants.Conventions.MediaTypes.Folder); mediaService.Save(folderMediaItem); } } //set the media root to the folder id so uploaded files will end there. parentId = folderMediaItem.Id; } } //get the files foreach (var file in result.FileData) { var fileName = file.Headers.ContentDisposition.FileName.Trim(new[] { '\"' }).TrimEnd(); var safeFileName = fileName.ToSafeFileName(); var ext = safeFileName.Substring(safeFileName.LastIndexOf('.') + 1).ToLower(); if (UmbracoConfig.For.UmbracoSettings().Content.IsFileAllowedForUpload(ext)) { var mediaType = Constants.Conventions.MediaTypes.File; if (result.FormData["contentTypeAlias"] == Constants.Conventions.MediaTypes.AutoSelect) { if (UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes.Contains(ext)) { mediaType = Constants.Conventions.MediaTypes.Image; } } else { mediaType = result.FormData["contentTypeAlias"]; } //TODO: make the media item name "nice" since file names could be pretty ugly, we have // string extensions to do much of this but we'll need: // * Pascalcase the name (use string extensions) // * strip the file extension // * underscores to spaces // * probably remove 'ugly' characters - let's discuss // All of this logic should exist in a string extensions method and be unit tested // http://issues.umbraco.org/issue/U4-5572 var mediaItemName = fileName; var f = mediaService.CreateMedia(mediaItemName, parentId, mediaType, Security.CurrentUser.Id); var fileInfo = new FileInfo(file.LocalFileName); var fs = fileInfo.OpenReadWithRetry(); if (fs == null) { throw new InvalidOperationException("Could not acquire file stream"); } using (fs) { f.SetValue(Constants.Conventions.Media.File, fileName, fs); } var saveResult = mediaService.WithResult().Save(f, Security.CurrentUser.Id); if (saveResult == false) { AddCancelMessage(tempFiles, message: Services.TextService.Localize("speechBubbles/operationCancelledText") + " -- " + mediaItemName, localizeMessage: false); } else { tempFiles.UploadedFiles.Add(new ContentItemFile { FileName = fileName, PropertyAlias = Constants.Conventions.Media.File, TempFilePath = file.LocalFileName }); } } else { tempFiles.Notifications.Add(new Notification( Services.TextService.Localize("speechBubbles/operationFailedHeader"), Services.TextService.Localize("media/disallowedFileType"), SpeechBubbleIcon.Warning)); } } //Different response if this is a 'blueimp' request if (Request.GetQueryNameValuePairs().Any(x => x.Key == "origin")) { var origin = Request.GetQueryNameValuePairs().First(x => x.Key == "origin"); if (origin.Value == "blueimp") { return(Request.CreateResponse(HttpStatusCode.OK, tempFiles, //Don't output the angular xsrf stuff, blue imp doesn't like that new JsonMediaTypeFormatter())); } } return(Request.CreateResponse(HttpStatusCode.OK, tempFiles)); }