开发者

Paperclip for asp.net mvc

开发者 https://www.devze.com 2023-02-11 06:14 出处:网络
Is it exists kind of plugin like Paperclip for Rails? it is really painful to implement own system for uploading files the resize it...

Is it exists kind of plugin like Paperclip for Rails?

it is really painful to implement own system for uploading files the resize it...

开发者_运维知识库will be cool to have Attribute for model that will get params like so:

Model:

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

View:

Html.Editor(x=>x.Image)

here is small tutorial for rails.


Looks like this question is pretty old, I've stumbled across it by accident and because it doesn't seem to be answered yet, I decided to bring my 2¢.

I don't know if such plugin exists for ASP.NET but it would be trivially easy to write one:

[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;
    }
}

then define a custom model binder for the HttpPostedFileBase type:

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);
        }
    }
}

which will be registered in Application_Start:

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

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

and we are pretty much done. All that's left is classic stuff.

View model:

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

Controller:

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");
    }
}

View:

@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" />
}
0

精彩评论

暂无评论...
验证码 换一张
取 消