asp.net-mvc - ASP.NET MVC 컨트롤러가 이미지를 반환 할 수 있습니까?




image controller (13)

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

SomeHelper.EmptyImageResult() 는 기존 이미지 (예 : 1x1 투명 SomeHelper.EmptyImageResult() 가있는 FileResult 를 반환해야합니다.

로컬 드라이브에 파일을 저장하는 것이 가장 쉬운 방법입니다. 파일이 byte[] 또는 stream 경우, Dylan이 제안한대로 FileContentResult 또는 FileStreamResult 를 사용하십시오.

이미지 애셋을 반환하는 Controller를 만들 수 있습니까?

다음과 같은 URL을 요청할 때마다 컨트롤러를 통해이 논리를 라우팅하고 싶습니다.

www.mywebsite.com/resource/image/topbanner

컨트롤러는 topbanner.png 를 검색하여 해당 이미지를 직접 클라이언트로 보냅니다.

보기를 생성해야하는 곳의 예를 보았습니다.보기를 사용하고 싶지 않습니다. 나는 컨트롤러만으로 모든 것을하고 싶다.

이것이 가능한가?


왜 간단하게 물결표 ~ 연산자를 사용하지 않습니까?

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

업데이트 : 내 원래의 답변보다 더 나은 옵션이 있습니다. 이것은 MVC 외부에서 잘 작동하지만 내장 된 이미지 내용 반환 방법을 고수하는 것이 좋습니다. 투표율이 높은 답변을 참조하십시오.

당신은 확실히 할 수 있습니다. 다음 단계를 시도해보십시오.

  1. 디스크에서 바이트 배열로 이미지로드
  2. 이미지에 대한 더 많은 요청을 원하고 디스크 I / O를 원하지 않는 경우 이미지를 캐시하십시오 (내 샘플은 캐시하지 않습니다)
  3. Response.ContentType을 통해 MIME 유형 변경
  4. Response.BinaryWrite 이미지 바이트 배열

다음은 몇 가지 샘플 코드입니다.

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

희망이 도움이됩니다!


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 밀리 초 (컨트롤러 평균은 68ms, 컨트롤러가 아닌 것은 65ms)였습니다.

여기에 나와있는 답변에서 언급 한 다른 방법 중 일부를 시도했지만 성능이 훨씬 더 극적이었습니다 ... 솔루션 응답 중 몇 가지는 비 컨트롤러 (다른 컨트롤러는 평균 340ms, 컨트롤러가 아닌 65ms)였습니다.


해결 방법 1 : 이미지 URL의 뷰에서 이미지 렌더링

나만의 확장 방법을 만들 수 있습니다.

public static MvcHtmlString Image(this HtmlHelper helper,string imageUrl)
{
   string tag = "<img src='{0}'/>";
   tag = string.Format(tag,imageUrl);
   return MvcHtmlString.Create(tag);
}

다음과 같이 사용하십시오.

@Html.Image(@Model.ImagePath);

해결 방법 2 : 데이터베이스에서 이미지 렌더링

아래처럼 이미지 데이터를 반환하는 컨트롤러 메서드를 만듭니다.

public sealed class ImageController : Controller
{
  public ActionResult View(string id)
  {
    var image = _images.LoadImage(id); //Pull image from the database.
    if (image == null) 
      return HttpNotFound();
    return File(image.Data, image.Mime);
  }
}

다음과 같은보기에서 사용하십시오.

@ { Html.RenderAction("View","Image",new {[email protected]})}

이 actionresult에서 렌더링 된 이미지를 HTML에서 사용하려면

<img src="http://something.com/image/view?id={imageid}>

딜란트의 반응에 대해 약간 알아보기 :

세 클래스는 FileResult 클래스를 구현합니다.

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

그들은 모두 상당히 자명하다.

  • 디스크에 파일이있는 파일 경로를 다운로드하려면 FilePathResult 사용하십시오. 이것은 가장 쉬운 방법이며 스트림을 사용하지 않아도됩니다.
  • byte [] 배열의 경우 (Response.BinaryWrite와 유사), FileContentResult 사용하십시오.
  • 파일을 다운로드하려는 바이트 [] 배열 (content-disposition : attachment)의 경우 FileStreamResult 를 다음과 비슷한 방식으로 사용하지만 MemoryStreamGetBuffer() .
  • Streams 경우 FileStreamResult 사용하십시오. 그것은 FileStreamResult라고하지만, 그것은 내가 MemoryStream 과 함께 작동 것 같아요 Stream 걸립니다.

다음은 내용 처리 기법 (테스트되지 않음)을 사용하는 예입니다.

    [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 ActionResult GetModifiedImage()
{
    Image image = Image.FromFile(Path.Combine(Server.MapPath("/Content/images"), "image.png"));

    using (Graphics g = Graphics.FromImage(image))
    {
        // do something with the Graphics (eg. write "Hello World!")
        string text = "Hello World!";

        // Create font and brush.
        Font drawFont = new Font("Arial", 10);
        SolidBrush drawBrush = new SolidBrush(Color.Black);

        // Create point for upper-left corner of drawing.
        PointF stringPoint = new PointF(0, 0);

        g.DrawString(text, drawFont, drawBrush, stringPoint);
    }

    MemoryStream ms = new MemoryStream();

    image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

    return File(ms.ToArray(), "image/png");
}

ContentResult를 살펴보십시오. 문자열을 반환하지만, 자신의 BinaryResult와 같은 클래스를 만드는 데 사용할 수 있습니다.


자신 만의 확장 프로그램을 만들어 이렇게 할 수 있습니다.

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 메소드를 사용하십시오.

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 밀리 초
  • 직접 : 사진 당 6.7 밀리 초

참고 : 이것은 요청의 평균 시간입니다. 평균은 로컬 시스템에서 수천 개의 요청을 수행하여 계산되었으므로 합계에는 네트워크 지연 또는 대역폭 문제가 없어야합니다.


파일을 사용하여보기, 내용 등의 파일을 반환 할 수 있습니다.

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

            }

HttpContext.Response를 사용하여 직접 내용을 쓸 수 있으며 (WriteFile ()이 효과적 일 수 있습니다) ActionResult 대신 Action에서 ContentResult를 반환합니다.

면책 조항 : 사용하지 않은 API를 살펴본 결과입니다. :-)


나는이 '문제'를 보았지만 name 속성을 추가함으로써 다소 논리적 인 해결책을 발견했다. 이 문제가 다른 언어로 떠 올랐습니다.

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2

  • ...
  • 양식에 두 개 이상의 제출 버튼이 포함되어있는 경우 활성화 된 제출 버튼 만 성공합니다.
  • ...

다음 코드 value 특성은 강력한 형식의 리소스 파일 또는 상수를 확인하는 추가 코드 가 필요 없이 변경, 지역화, 국제화 될 수 있습니다.

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="send" value="Send" />
<input type="submit" name="cancel" value="Cancel" />
<input type="submit" name="draft" value="Save as draft" />
<% Html.EndForm(); %>`

수신 측에서는 알려진 제출 유형이 null 이 아닌지 확인 null

public ActionResult YourAction(YourModel model) {

    if(Request["send"] != null) {

        // we got a send

    }else if(Request["cancel"]) {

        // we got a cancel, but would you really want to post data for this?

    }else if(Request["draft"]) {

        // we got a draft

    }

}




asp.net asp.net-mvc image controller