یک ادیتور آنلاین را تصور کنید که کاربران در قسمت ارسال تصویر آن قرار است فقط فایلهای png، jpg و gif ارسال کنند و نه مثلا فایل test.aspx و موارد مشابه. در اینجا برای محدود کردن نوع فایلهای آپلود شده میتوان از فیلترهای سفارشی ASP.NET MVC کمک گرفت:
کد:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
namespace SecurityModule
{
public class AllowUploadSpecialFilesOnlyAttribute : ActionFilterAttribute
{
readonly List<string> _toFilter = new List<string>();
readonly string _extensionsWhiteList;
public AllowUploadSpecialFilesOnlyAttribute(string extensionsWhiteList)
{
if (string.IsNullOrWhiteSpace(extensionsWhiteList))
throw new ArgumentNullException("extensionsWhiteList");
_extensionsWhiteList = extensionsWhiteList;
var extensions = extensionsWhiteList.Split(',');
foreach (var ext in extensions.Where(ext => !string.IsNullOrWhiteSpace(ext)))
{
_toFilter.Add(ext.ToLowerInvariant().Trim());
}
}
bool canUpload(string fileName)
{
if (string.IsNullOrWhiteSpace(fileName)) return false;
var ext = Path.GetExtension(fileName.ToLowerInvariant());
return _toFilter.Contains(ext);
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var files = filterContext.HttpContext.Request.Files;
foreach (string file in files)
{
var postedFile = files[file];
if (postedFile == null || postedFile.ContentLength == 0) continue;
if (!canUpload(postedFile.FileName))
throw new InvalidOperationException(
string.Format("You are not allowed to upload {0} file. Please upload only these files: {1}.",
Path.GetFileName(postedFile.FileName),
_extensionsWhiteList));
}
base.OnActionExecuting(filterContext);
}
}
}
توضیحات کدهای فوق:
برای تهیه فیلتر محدود سازی نوع فایلهای قابل ارسال به سرور، با ارث بری از ActionFilterAttribute شروع خواهیم کرد. سپس با تحریف متد OnActionExecuting آن، توسط filterContext.HttpContext.Request.Files میتوان به کلیه فایلهای درحال ارسال به سرور در طی درخواست جاری، دسترسی یافت.
به این ترتیب از طریق مقدار خاصیت postedFile.FileName میتوان به پسوند فایل در حال ارسال رسید و بر این اساس امکان ارسال فایلهای غیرمجاز را در نیمه راه با صدور یک استثناء سلب کرد.
برای استفاده از این فیلتر سفارشی تهیه شده نیز میتوان به نحو زیر عمل کرد:
کد:
[AllowUploadSpecialFilesOnly(".jpg,.gif,.png")]
public ActionResult ImageUpload(HttpPostedFileBase file)
در اینجا پسوند فایلهای مجاز قابل ارسال، توسط یک کاما از هم جدا خواهند شد.
یک نکته تکمیلی:
اگر کاربر قرار است تنها تصویر ارسال کند، بررسی پسوند فایل لازم است اما کافی نیست. برای این منظور میتوان از کلاس Image واقع شده در فضای نام System.Drawing نیز کمک گرفت:
کد:
public static bool IsImageFile(HttpPostedFileBase photoFile)
{
using (var img = Image.FromStream(photoFile.InputStream))
{
return img.Width > 0;
}
}
در اینجا اگر فایل ارسالی تصویر نباشد، به صورت خودکار یک استثناء صادر خواهد شد.