asp.net - custom - mvc validation




هل تستطيع وحدة تحكم ASP.NET MVC عرض صورة؟ (11)

أرى خيارين:

1) تنفيذ IViewEngine الخاصة بك وتعيين الخاصية ViewEngine من وحدة تحكم كنت تستخدم ل ImageViewEngine الخاص بك في طريقة "صورة" المطلوب.

2) استخدم طريقة العرض :-). ما عليك سوى تغيير نوع المحتوى وما إلى ذلك.

هل يمكنني إنشاء وحدة تحكم تقوم فقط بإرجاع أصل الصورة؟

أود توجيه هذا المنطق من خلال جهاز تحكم ، كلما طلب عنوان URL مثل ما يلي:

www.mywebsite.com/resource/image/topbanner

سوف تبحث وحدة التحكم عن topbanner.png وترسل تلك الصورة مباشرة إلى العميل.

لقد رأيت أمثلة على ذلك حيث يجب عليك إنشاء عرض - لا أريد استخدام طريقة عرض. أريد أن أفعل كل ذلك فقط مع المراقب المالي.

هل هذا ممكن؟


استخدم أسلوب "التحكم الأساسي" في الملفات.

public ActionResult Image(string id)
{
    var dir = Server.MapPath("/Images");
    var path = Path.Combine(dir, id + ".jpg"); //validate the path for security or use other means to generate the path.
    return base.File(path, "image/jpeg");
}

كملاحظة ، يبدو أن هذا فعال إلى حد ما. لقد أجريت اختبارًا حيث طلبت الصورة من خلال وحدة التحكم ( http://localhost/MyController/Image/MyImage ) وعبر عنوان URL المباشر ( http://localhost/Images/MyImage.jpg ) وكانت النتائج:

  • MVC: 7.6 ميلي ثانية لكل صورة
  • Direct: 6.7 مللي ثانية لكل صورة

ملاحظة: هذا هو متوسط ​​وقت الطلب. تم حساب المتوسط ​​عن طريق جعل الآلاف من الطلبات على الجهاز المحلي ، لذلك لا يجب أن تتضمن الإجماليات وقت استجابة الشبكة أو مشكلة عرض النطاق الترددي.


باستخدام نسخة إصدار MVC ، إليك ما أقوم به:

[AcceptVerbs(HttpVerbs.Get)]
[OutputCache(CacheProfile = "CustomerImages")]
public FileResult Show(int customerId, string imageName)
{
    var path = string.Concat(ConfigData.ImagesDirectory, customerId, "\\", imageName);
    return new FileStreamResult(new FileStream(path, FileMode.Open), "image/jpeg");
}

من الواضح أن لدي بعض الأشياء الخاصة بالتطبيق هنا فيما يتعلق ببناء المسار ، ولكن إرجاع FileStreamResult هو أمر لطيف وبسيط.

أجريت بعض اختبارات الأداء فيما يتعلق بهذا الإجراء ضد مكالمتك اليومية للصورة (تجاوز جهاز التحكم) وكان الفرق بين المتوسطات حوالي 3 مللي ثانية فقط (كان متوسط ​​وحدة التحكم 68 مللي ثانية ، وكان جهاز التحكم غير 65 مللي ثانية).

لقد جربت بعض الطرق الأخرى المذكورة في الإجابات هنا وكان أداءها أكثر دراماتيكية ... العديد من استجابات الحلول كانت بقدر 6x غير المتحكم (وحدات التحكم الأخرى avg 340ms ، 65-x غير تحكم).



لفضاء على استجابة Dyland قليلا:

ثلاث فئات تطبيق فئة FileResult :

System.Web.Mvc.FileResult
      System.Web.Mvc.FileContentResult
      System.Web.Mvc.FilePathResult
      System.Web.Mvc.FileStreamResult

انهم جميعا تفسيرية النفس إلى حد ما:

  • بالنسبة لتنزيلات مسار الملفات حيث يوجد الملف على القرص ، استخدم FilePathResult - هذه هي الطريقة الأسهل وتجنب استخدام تيارات.
  • للحصول على صفيف [] بايت [أقرب إلى Response.BinaryWrite) ، استخدم FileContentResult .
  • بالنسبة إلى صفيفات البايت [] حيث تريد تنزيل الملف (content-disposition: attachment) ، استخدم FileStreamResult بالطريقة نفسها أدناه ، ولكن باستخدام MemoryStream واستخدام GetBuffer() .
  • Streams استخدام FileStreamResult . يطلق عليه FileStreamResult لكنه يأخذ Stream لذلك أعتقد أنه يعمل مع MemoryStream .

فيما يلي مثال على استخدام تقنية تصرف المحتوى (لم يتم اختبارها):

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult GetFile()
    {
        // No need to dispose the stream, MVC does it for you
        string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "myimage.png");
        FileStream stream = new FileStream(path, FileMode.Open);
        FileStreamResult result = new FileStreamResult(stream, "image/png");
        result.FileDownloadName = "image.png";
        return result;
    }

لماذا لا تذهب بسيطة واستخدام المشغل تيلدا ~ ؟

public FileResult TopBanner() {
  return File("~/Content/images/topbanner.png", "image/png");
}

يمكنك إنشاء ملحق خاص بك والقيام بهذه الطريقة.

public static class ImageResultHelper
{
    public static string Image<T>(this HtmlHelper helper, Expression<Action<T>> action, int width, int height)
            where T : Controller
    {
        return ImageResultHelper.Image<T>(helper, action, width, height, "");
    }

    public static string Image<T>(this HtmlHelper helper, Expression<Action<T>> action, int width, int height, string alt)
            where T : Controller
    {
        var expression = action.Body as MethodCallExpression;
        string actionMethodName = string.Empty;
        if (expression != null)
        {
            actionMethodName = expression.Method.Name;
        }
        string url = new UrlHelper(helper.ViewContext.RequestContext, helper.RouteCollection).Action(actionMethodName, typeof(T).Name.Remove(typeof(T).Name.IndexOf("Controller"))).ToString();         
        //string url = LinkBuilder.BuildUrlFromExpression<T>(helper.ViewContext.RequestContext, helper.RouteCollection, action);
        return string.Format("<img src=\"{0}\" width=\"{1}\" height=\"{2}\" alt=\"{3}\" />", url, width, height, alt);
    }
}

public class ImageResult : ActionResult
{
    public ImageResult() { }

    public Image Image { get; set; }
    public ImageFormat ImageFormat { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        // verify properties 
        if (Image == null)
        {
            throw new ArgumentNullException("Image");
        }
        if (ImageFormat == null)
        {
            throw new ArgumentNullException("ImageFormat");
        }

        // output 
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.ContentType = GetMimeType(ImageFormat);
        Image.Save(context.HttpContext.Response.OutputStream, ImageFormat);
    }

    private static string GetMimeType(ImageFormat imageFormat)
    {
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
        return codecs.First(codec => codec.FormatID == imageFormat.Guid).MimeType;
    }
}
public ActionResult Index()
    {
  return new ImageResult { Image = image, ImageFormat = ImageFormat.Jpeg };
    }
    <%=Html.Image<CapchaController>(c => c.Index(), 120, 30, "Current time")%>

يمكنك استخدام File لإرجاع ملف مثل View، Content etc

 public ActionResult PrintDocInfo(string Attachment)
            {
                string test = Attachment;
                if (test != string.Empty || test != "" || test != null)
                {
                    string filename = Attachment.Split('\\').Last();
                    string filepath = Attachment;
                    byte[] filedata = System.IO.File.ReadAllBytes(Attachment);
                    string contentType = MimeMapping.GetMimeMapping(Attachment);

                    System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
                    {
                        FileName = filename,
                        Inline = true,
                    };

                    Response.AppendHeader("Content-Disposition", cd.ToString());

                    return File(filedata, contentType);          
                }
                else { return Content("<h3> Patient Clinical Document Not Uploaded</h3>"); }

            }

يمكنك الكتابة مباشرة إلى الرد ولكن بعد ذلك لا يمكن اختباره. يفضل إرجاع ActionResult له تأجيل التنفيذ. هنا هو بلدي StreamResult قابلة لإعادة الاستخدام:

public class StreamResult : ViewResult
{
    public Stream Stream { get; set; }
    public string ContentType { get; set; }
    public string ETag { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = ContentType;
        if (ETag != null) context.HttpContext.Response.AddHeader("ETag", ETag);
        const int size = 4096;
        byte[] bytes = new byte[size];
        int numBytes;
        while ((numBytes = Stream.Read(bytes, 0, size)) > 0)
            context.HttpContext.Response.OutputStream.Write(bytes, 0, numBytes);
    }
}

استكمال: هناك خيارات أفضل من جوابي الأصلي. هذا يعمل خارج MVC بشكل جيد ولكن من الأفضل الالتزام بالأساليب المضمنة لإعادة محتوى الصورة. الاطلاع على الإجابات صعودًا.

يمكنك بالتأكيد. جرب هذه الخطوات:

  1. قم بتحميل الصورة من القرص إلى صفيف بايت
  2. تخزين الصورة في الحالة التي تتوقع فيها المزيد من الطلبات للصورة ولا تريد إدخال / إخراج القرص (لا تخزن العينة مؤقتًا أدناه)
  3. قم بتغيير نوع mime عبر Response.ContentType
  4. Response.BinaryWrite خارج مجموعة بايت الصورة

إليك بعض نماذج التعليمة البرمجية:

string pathToFile = @"C:\Documents and Settings\some_path.jpg";
byte[] imageData = File.ReadAllBytes(pathToFile);
Response.ContentType = "image/jpg";
Response.BinaryWrite(imageData);

امل ان يساعد!


if (!System.IO.File.Exists(filePath))
    return SomeHelper.EmptyImageResult(); // preventing JSON GET/POST exception
else
    return new FilePathResult(filePath, contentType);

يجب أن ترجع SomeHelper.EmptyImageResult() FileResult مع الصورة الموجودة (1 × 1 شفاف ، على سبيل المثال).

هذه أسهل طريقة إذا كان لديك ملفات مخزنة على محرك أقراص محلي. إذا كانت الملفات byte[] أو stream - ثم استخدم FileContentResult أو FileStreamResult كما اقترح ديلان.





controller