Media service
This commit is contained in:
@@ -17,6 +17,9 @@ data-file-upload="options" data-ng-class="{'fileupload-processing': processing()
|
||||
</div>
|
||||
|
||||
<div class="pull-right umb-btn-toolbar">
|
||||
|
||||
{{progress | json}}
|
||||
|
||||
<span class="btn fileinput-button" ng-class="{disabled: disabled}">
|
||||
<i class="icon-upload"></i>
|
||||
<input type="file" name="files[]" multiple ng-disabled="disabled">
|
||||
@@ -33,9 +36,13 @@ data-file-upload="options" data-ng-class="{'fileupload-processing': processing()
|
||||
|
||||
<ul class="breadcrumb">
|
||||
<li><strong>You are here:</strong></li>
|
||||
<li><a href="#">Media</a></li>
|
||||
<li><a href ng-click="gotoFolder(-1)" prevent-default>Media</a></li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
{{queue | json}}
|
||||
|
||||
<table class="table table-striped files ng-cloak">
|
||||
<tr data-ng-repeat="file in queue">
|
||||
<td>
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace Umbraco.Web.Editors
|
||||
//API URLs
|
||||
{"contentApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentController>("PostSave")},
|
||||
{"mediaApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaController>("GetRootMedia")},
|
||||
{"mediaUploadApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaUploadController>("Post")},
|
||||
{"sectionApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<SectionController>("GetSections")},
|
||||
{"treeApplicationApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ApplicationTreeController>("GetApplicationTrees")},
|
||||
{"contentTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentTypeController>("GetAllowedChildren")},
|
||||
|
||||
260
src/Umbraco.Web/Editors/MediaUploadController.cs
Normal file
260
src/Umbraco.Web/Editors/MediaUploadController.cs
Normal file
@@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Script.Serialization;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
/*
|
||||
* WebApi Implementation: Luke Baughan https://github.com/bUKaneer/jQuery-File-Upload
|
||||
* based on HttpHandler Implementation: Max Pavlov https://github.com/maxpavlov/jQuery-File-Upload.MVC3
|
||||
*/
|
||||
|
||||
[PluginController("UmbracoApi")]
|
||||
public class MediaUploadController : UmbracoApiController
|
||||
{
|
||||
private readonly JavaScriptSerializer _js = new JavaScriptSerializer { MaxJsonLength = 41943040 };
|
||||
private readonly string _storageRoot = Core.IO.IOHelper.MapPath( Core.IO.SystemDirectories.Media );
|
||||
public bool _isReusable { get { return false; } }
|
||||
|
||||
|
||||
public string Meh()
|
||||
{
|
||||
return "wo";
|
||||
}
|
||||
|
||||
|
||||
#region Get
|
||||
private HttpResponseMessage DownloadFileContent()
|
||||
{
|
||||
var filename = HttpContext.Current.Request["f"];
|
||||
var filePath = _storageRoot + filename;
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
|
||||
response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
|
||||
{
|
||||
FileName = filename
|
||||
};
|
||||
return response;
|
||||
}
|
||||
return ControllerContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, "");
|
||||
}
|
||||
|
||||
private HttpResponseMessage DownloadFileList()
|
||||
{
|
||||
var files =
|
||||
new DirectoryInfo(_storageRoot)
|
||||
.GetFiles("*", SearchOption.TopDirectoryOnly)
|
||||
.Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden))
|
||||
.Select(f => new FilesStatus(f))
|
||||
.ToArray();
|
||||
HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline; filename=\"files.json\"");
|
||||
return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, _js.Serialize(files));
|
||||
}
|
||||
|
||||
|
||||
public HttpResponseMessage Get()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(HttpContext.Current.Request["f"]))
|
||||
{
|
||||
return DownloadFileContent();
|
||||
}
|
||||
return DownloadFileList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Post & Put
|
||||
public HttpResponseMessage Post()
|
||||
{
|
||||
return UploadFile(HttpContext.Current);
|
||||
}
|
||||
|
||||
public HttpResponseMessage Put()
|
||||
{
|
||||
return UploadFile(HttpContext.Current);
|
||||
}
|
||||
|
||||
private HttpResponseMessage UploadFile(HttpContext context)
|
||||
{
|
||||
var statuses = new List<FilesStatus>();
|
||||
var headers = context.Request.Headers;
|
||||
|
||||
if (string.IsNullOrEmpty(headers["X-File-Name"]))
|
||||
{
|
||||
UploadWholeFile(context, statuses);
|
||||
}
|
||||
else
|
||||
{
|
||||
UploadPartialFile(headers["X-File-Name"], context, statuses);
|
||||
}
|
||||
|
||||
return WriteJsonIframeSafe(context, statuses);
|
||||
}
|
||||
|
||||
private HttpResponseMessage WriteJsonIframeSafe(HttpContext context, List<FilesStatus> statuses)
|
||||
{
|
||||
context.Response.AddHeader("Vary", "Accept");
|
||||
var response = new HttpResponseMessage()
|
||||
{
|
||||
Content = new StringContent(_js.Serialize(statuses.ToArray()))
|
||||
};
|
||||
if (context.Request["HTTP_ACCEPT"].Contains("application/json"))
|
||||
{
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
}
|
||||
else
|
||||
{
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
// Upload partial file
|
||||
private void UploadPartialFile(string fileName, HttpContext context, List<FilesStatus> statuses)
|
||||
{
|
||||
if (context.Request.Files.Count != 1) throw new HttpRequestValidationException("Attempt to upload chunked file containing more than one fragment per request");
|
||||
var inputStream = context.Request.Files[0].InputStream;
|
||||
var fullName = _storageRoot + Path.GetFileName(fileName);
|
||||
|
||||
using (var fs = new FileStream(fullName, FileMode.Append, FileAccess.Write))
|
||||
{
|
||||
var buffer = new byte[1024];
|
||||
|
||||
var l = inputStream.Read(buffer, 0, 1024);
|
||||
while (l > 0)
|
||||
{
|
||||
fs.Write(buffer, 0, l);
|
||||
l = inputStream.Read(buffer, 0, 1024);
|
||||
}
|
||||
fs.Flush();
|
||||
fs.Close();
|
||||
}
|
||||
statuses.Add(new FilesStatus(new FileInfo(fullName)));
|
||||
}
|
||||
|
||||
// Upload entire file
|
||||
private void UploadWholeFile(HttpContext context, List<FilesStatus> statuses)
|
||||
{
|
||||
for (int i = 0; i < context.Request.Files.Count; i++)
|
||||
{
|
||||
var file = context.Request.Files[i];
|
||||
string fullPath = _storageRoot + Path.GetFileName(file.FileName);
|
||||
Directory.CreateDirectory(_storageRoot);
|
||||
|
||||
file.SaveAs(fullPath);
|
||||
string fullName = Path.GetFileName(file.FileName);
|
||||
statuses.Add(new FilesStatus(fullName, file.ContentLength, fullPath));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Delete
|
||||
public HttpResponseMessage Delete()
|
||||
{
|
||||
var filePath = _storageRoot + HttpContext.Current.Request["f"];
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, "");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region FileStatus
|
||||
public class FilesStatus
|
||||
{
|
||||
public const string HandlerPath = "/";
|
||||
|
||||
public string group { get; set; }
|
||||
public string name { get; set; }
|
||||
public string type { get; set; }
|
||||
public int size { get; set; }
|
||||
public string progress { get; set; }
|
||||
public string url { get; set; }
|
||||
public string thumbnail_url { get; set; }
|
||||
public string delete_url { get; set; }
|
||||
public string delete_type { get; set; }
|
||||
public string error { get; set; }
|
||||
|
||||
public FilesStatus()
|
||||
{
|
||||
}
|
||||
|
||||
public FilesStatus(FileInfo fileInfo)
|
||||
{
|
||||
SetValues(fileInfo.Name, (int)fileInfo.Length, fileInfo.FullName);
|
||||
}
|
||||
|
||||
public FilesStatus(string fileName, int fileLength, string fullPath)
|
||||
{
|
||||
SetValues(fileName, fileLength, fullPath);
|
||||
}
|
||||
|
||||
private void SetValues(string fileName, int fileLength, string fullPath)
|
||||
{
|
||||
name = fileName;
|
||||
type = "image/png";
|
||||
size = fileLength;
|
||||
progress = "1.0";
|
||||
url = HandlerPath + "api/Upload?f=" + fileName;
|
||||
delete_url = HandlerPath + "api/Upload?f=" + fileName;
|
||||
delete_type = "DELETE";
|
||||
var ext = Path.GetExtension(fullPath);
|
||||
var fileSize = ConvertBytesToMegabytes(new FileInfo(fullPath).Length);
|
||||
if (fileSize > 3 || !IsImage(ext))
|
||||
{
|
||||
thumbnail_url = "/Content/img/generalFile.png";
|
||||
}
|
||||
else
|
||||
{
|
||||
thumbnail_url = @"data:image/png;base64," + EncodeFile(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsImage(string ext)
|
||||
{
|
||||
return ext == ".gif" || ext == ".jpg" || ext == ".png";
|
||||
}
|
||||
|
||||
private string EncodeFile(string fileName)
|
||||
{
|
||||
byte[] bytes;
|
||||
using (Image image = Image.FromFile(fileName))
|
||||
{
|
||||
var ratioX = (double)80 / image.Width;
|
||||
var ratioY = (double)80 / image.Height;
|
||||
var ratio = Math.Min(ratioX, ratioY);
|
||||
var newWidth = (int)(image.Width * ratio);
|
||||
var newHeight = (int)(image.Height * ratio);
|
||||
var newImage = new Bitmap(newWidth, newHeight);
|
||||
Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
|
||||
ImageConverter converter = new ImageConverter();
|
||||
bytes = (byte[])converter.ConvertTo(newImage, typeof(byte[]));
|
||||
newImage.Dispose();
|
||||
}
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
|
||||
private static double ConvertBytesToMegabytes(long bytes)
|
||||
{
|
||||
return (bytes / 1024f) / 1024f;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user