Скрепка для asp.net mvc - PullRequest
       13

Скрепка для asp.net mvc

4 голосов
/ 16 февраля 2011

Существует ли такой плагин, как Paperclip for Rails?

действительно трудно реализовать собственную систему для загрузки файлов, изменить ее размер ...

будет здорово иметь атрибут дляМодель, которая получит параметры следующим образом:

Модель:

[Paperclip(Sizes={thumb="100x20",big="200x40"},Path="~/public/")]
public string Image{get;set;}

Вид:

Html.Editor(x=>x.Image)

Вот небольшой учебник для рельсов .

1 Ответ

10 голосов
/ 24 сентября 2011

Похоже, этот вопрос довольно старый, я случайно наткнулся на него, и, поскольку на него, похоже, пока нет ответа, я решил принести свои 2 ¢.

Я не знаю, существует ли такой плагин для ASP.NET, но было бы легко написать его:

[AttributeUsage(AttributeTargets.Property)]
public class PaperClipAttribute : Attribute, IMetadataAware
{
    public PaperClipAttribute(string uploadPath, params string[] sizes)
    {
        if (string.IsNullOrEmpty(uploadPath))
        {
            throw new ArgumentException("Please specify an upload path");
        }

        UploadPath = uploadPath;
        Sizes = sizes;
    }

    public string UploadPath { get; private set; }
    public string[] Sizes { get; private set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["PaperClip"] = this;
    }
}

, а затем определить пользовательский механизм связывания для типа HttpPostedFileBase:

public class PaperClipModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var paperClip = bindingContext.ModelMetadata.AdditionalValues["PaperClip"] as PaperClipAttribute;
        if (paperClip == null)
        {
            return base.BindModel(controllerContext, bindingContext);
        }

        var uploadedFile = base.BindModel(controllerContext, bindingContext) as HttpPostedFileBase;
        if (uploadedFile == null)
        {
            return null;
        }

        var uploadPath = controllerContext.HttpContext.Server.MapPath(paperClip.UploadPath);
        if (!Directory.Exists(uploadPath))
        {
            throw new ArgumentException(string.Format("The specified folder \"{0}\" does not exist", uploadPath));
        }
        var sizes =
            (from size in paperClip.Sizes
             let tokens = size.Split('x')
             select new Size(int.Parse(tokens[0]), int.Parse(tokens[1]))
            ).ToArray();

        foreach (var size in sizes)
        {
            var extension = Path.GetExtension(uploadedFile.FileName);
            var outputFilename = Path.Combine(
                uploadPath,
                Path.ChangeExtension(
                    string.Format("image{0}x{1}", size.Width, size.Height),
                    extension
                )
            );
            Resize(uploadedFile.InputStream, outputFilename, size);
        }

        return base.BindModel(controllerContext, bindingContext);
    }

    private void Resize(Stream input, string outputFile, Size size)
    {
        using (var image = Image.FromStream(input))
        using (var bmp = new Bitmap(size.Width, size.Height))
        using (var gr = Graphics.FromImage(bmp))
        {
            gr.CompositingQuality = CompositingQuality.HighSpeed;
            gr.SmoothingMode = SmoothingMode.HighSpeed;
            gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
            gr.DrawImage(image, new Rectangle(0, 0, size.Width, size.Height));
            bmp.Save(outputFile);
        }
    }
}

, который будет зарегистрирован в Application_Start:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    ModelBinders.Binders[typeof(HttpPostedFileBase)] = new PaperClipModelBinder();
}

, и мы почти закончили.Все, что осталось, - это классические вещи.

Посмотреть модель:

public class MyViewModel
{
    [PaperClip("~/App_Data", "100x20", "200x40", "640x480")]
    [Required(ErrorMessage = "Please select a file to upload")]
    public HttpPostedFileBase Image { get; set; }
}

Контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }
        return Content("thanks for uploading");
    }
}

Просмотр:

@model MyViewModel

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{ 
    @Html.LabelFor(x => x.Image)
    <input type="file" name="image" />
    @Html.ValidationMessageFor(x => x.Image)
    <input type="submit" value="Upload" />
}
...