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);
}
}
2
您可以创建自己的扩展并以此方式执行 .
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")%>
8
您可以使用File返回View,Content等文件
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>"); }
}
0
UPDATE: There are better options than my original answer. This works outside of MVC quite well but it's better to stick with the built-in methods of returning image content. See up-voted answers.
Solution 1: To render an image in a view from an image 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);
Solution 2: To render image from database
创建一个返回如下图像数据的控制器方法
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);
}
}
[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;
}
0
如果您想在返回之前修改图像,这可能会有所帮助:
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");
}
1
if (!System.IO.File.Exists(filePath))
return SomeHelper.EmptyImageResult(); // preventing JSON GET/POST exception
else
return new FilePathResult(filePath, contentType);
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");
}
15 回答
为什么不简单并使用波浪号
~
运算符?我看到两个选择:
1)实现您自己的IViewEngine,并在您想要的“图像”方法中将您正在使用的Controller的ViewEngine属性设置为ImageViewEngine .
2)使用视图:-) . 只需更改内容类型等 .
看看ContentResult . 这将返回一个字符串,但可用于创建自己的BinaryResult类 .
您可以直接写入响应,但它不可测试 . 最好返回具有延迟执行的ActionResult . 这是我可重复使用的StreamResult:
您可以创建自己的扩展并以此方式执行 .
您可以使用File返回View,Content等文件
UPDATE: There are better options than my original answer. This works outside of MVC quite well but it's better to stick with the built-in methods of returning image content. See up-voted answers.
你当然可以 . 尝试以下步骤:
将映像从磁盘加载到字节数组中
如果您期望对图像发出更多请求,请
缓存图像,并在下面缓存它 .
通过Response.ContentType更改mime类型
Response.BinaryWrite out图像字节数组
这是一些示例代码:
希望有所帮助!
Solution 1: To render an image in a view from an image URL
您可以创建自己的扩展方法:
然后使用它像:
Solution 2: To render image from database
创建一个返回如下图像数据的控制器方法
并在以下视图中使用它:
要在任何HTML中使用从此actionresult渲染的图像,请使用
稍微解释一下Dyland的反应:
三个类实现FileResult类:
他们都是相当自我解释的:
对于文件存在于磁盘上的文件路径下载,请使用
FilePathResult
- 这是最简单的方法,避免使用Streams .对于byte []数组(类似于Response.BinaryWrite),请使用
FileContentResult
.对于您希望文件下载的byte []数组(内容处理:附件),请使用
FileStreamResult
,方法与下面类似,但使用MemoryStream
并使用GetBuffer()
.对于
Streams
使用FileStreamResult
. 它被称为FileStreamResult,但需要Stream
所以我猜它适用于MemoryStream
.下面是使用内容处理技术(未测试)的示例:
如果您想在返回之前修改图像,这可能会有所帮助:
SomeHelper.EmptyImageResult()
应该使用现有图像返回FileResult
(例如,1x1透明) .如果您将文件存储在本地驱动器上,这是最简单的方法 . 如果文件是
byte[]
或stream
- 则使用FileContentResult
或FileStreamResult
作为Dylan建议 .使用基本控制器File方法 .
需要注意的是,这似乎相当有效 . 我做了一个测试,我通过控制器(
http://localhost/MyController/Image/MyImage
)和直接URL(http://localhost/Images/MyImage.jpg
)请求图像,结果如下:MVC: 每张照片7.6毫秒
Direct: 每张照片6.7毫秒
注意:这是请求的平均时间 . 通过在本地计算机上发出数千个请求来计算平均值,因此总计不应包括网络延迟或带宽问题 .
这对我有用 . 因为我将图像存储在SQL Server数据库中 .
在上面的代码片段中,
_db.ImageFiles.Find(uuid)
正在db(EF上下文)中搜索图像文件记录 . 它返回一个FileImage对象,它只是我为模型制作的自定义类,然后将其用作FileContentResult .您可以使用HttpContext.Response并直接将内容写入其中(WriteFile()可能适合您),然后从您的操作而不是ActionResult返回ContentResult .
免责声明:我没有尝试过这个,它基于查看可用的API . :-)
使用MVC的发布版本,我就是这样做的:
我显然在这里有一些关于路径构造的应用程序特定的东西,但是FileStreamResult的返回很简单 .
我针对您每天对图像的调用(绕过控制器)执行了一些性能测试,平均值之间的差异仅为3毫秒(控制器平均值为68毫秒,非控制器为65毫秒) .
我已经尝试过这里的答案中提到的其他一些方法,性能影响要大得多......几个解决方案的响应是非控制器的6倍(其他控制器平均340毫秒,非控制器65毫秒) .