首页 > 代码库 > ASP.NET MVC 拓展ViewResult实现word文档下载

ASP.NET MVC 拓展ViewResult实现word文档下载

?

最近项目中有同事用到word文档导出功能,遇到了一些导出失败问题,帮其看了下解决问题的同事,看了下之前的代码发现几个问题:

  1. 代码编写不规范,word导出功能未收口
  2. 重复代码导出都是
  3. 实现逻辑比较复杂,不易于维护及使用

在帮其解决问题后,写了下面这个ViewResult拓展,依赖Razor视图,能够直接转换页面为word文档,但是不支持外联样式表,样式可以定义在<head>头部

废话不多说,直接上代码:

?

public class WordFileResult : ViewResultBase

{

public string FileName { get; set; }

?

public WordFileResult(object model, string viewName, string fileName)

{

ViewData = http://www.mamicode.com/new ViewDataDictionary(model);

ViewName = viewName;

FileName = fileName;

}

?

public WordFileResult() : this(new ViewDataDictionary(), null, null)

{

?

}

?

public WordFileResult(string fileName) : this(new ViewDataDictionary(), null, fileName)

{

?

}

?

public WordFileResult(object model) : this(model, null, null)

{

?

}

?

public WordFileResult(object model, string fileName) : this(model, null, fileName)

{

?

}

?

protected override ViewEngineResult FindView(ControllerContext context)

{

context.HttpContext.Response.Charset = "utf-8";

context.HttpContext.Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");

if (string.IsNullOrWhiteSpace(FileName))

{

FileName = ViewName;

}

context.HttpContext.Response.AppendHeader("Content-Disposition", string.Format("filename={0}.doc", FileName));

context.HttpContext.Response.ContentType = "application/msword";

ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, string.Empty);

if (result.View != null)

{

return result;

}

return null;

}

}

?

?

public static class ControllerExtensions

{

public static WordFileResult Word(this Controller controller, object model)

{

return new WordFileResult(model);

}

?

public static WordFileResult Word(this Controller controller, object model, string fileName)

{

return new WordFileResult(model, fileName);

}

?

public static WordFileResult Word(this Controller controller, string fileName)

{

return new WordFileResult(fileName);

}

?

public static WordFileResult Word(this Controller controller, object model, string viewName, string fileName)

{

return new WordFileResult(model, viewName, fileName);

}

?

?

}

?

使用方式比较简单:

  1. 定义视图,使用Razor视图布局word内容,

@using RazorWord.Models

@model List<LoginViewModel>

@{

Layout = null;

}

?

<!DOCTYPE html>

?

<html>

<head>

<meta name="viewport" content="width=device-width" />

<title>Export</title>

<style type="text/css">

.table td,

.table th {

background-color: #fff !important;

}

?

.table {

border-collapse: collapse !important;

background-color: #ffffff;

width: 100%;

margin-bottom: 20px;

}

?

.table thead > tr > th,

.table tbody > tr > th,

.table tfoot > tr > th,

.table thead > tr > td,

.table tbody > tr > td,

.table tfoot > tr > td {

padding: 8px;

line-height: 1.428571429;

vertical-align: top;

border-top: 1px solid #dddddd;

}

?

.table thead > tr > th {

vertical-align: bottom;

border-bottom: 2px solid #dddddd;

}

</style>

</head>

<body>

<div>

<table class="table">

<tr>

<th>电子邮件</th>

<th>密码</th>

<th>是否记住密码</th>

</tr>

@foreach (LoginViewModel item in Model)

{

<tr>

<td>@item.Email</td>

<td>@item.Password]</td>

<td>@(item.RememberMe ? "Y" : "N")</td>

</tr>

}

</table>

</div>

</body>

</html>

?

  1. 添加Action修改对应的Action方法返回值

?

public ActionResult Export()

{

List<LoginViewModel> models = new List<LoginViewModel>();

for (int i = 0; i < 20; i++)

{

models.Add(new LoginViewModel()

{

Email = $"{i}user@123.com",

Password = new Random().Next(1, 10000).ToString(),

RememberMe = i % 2 == 0 ? true : false

});

}

?

return new WordFileResult(models, "下载文件名称");

}

?

public ActionResult Export1()

{

List<LoginViewModel> models = new List<LoginViewModel>();

for (int i = 0; i < 20; i++)

{

models.Add(new LoginViewModel()

{

Email = $"{i}user@123.com",

Password = new Random().Next(1, 10000).ToString(),

RememberMe = i % 2 == 0 ? true : false

});

}

return this.Word(models, "Export", "下载文件名称");

}

?

?

还有一种更方便的方式:使用ActionFilterAttribute过滤器

直接上代码:

public class WordDocumentAttribute : ActionFilterAttribute

{

public string FileName { get; set; }

public override void OnResultExecuted(ResultExecutedContext filterContext)

{

var result = filterContext.Result as ViewResult;

if (string.IsNullOrWhiteSpace(FileName))

{

FileName = result == null ? DateTime.Now.ToString("yyyy_MM_dd") : result.ViewName;

}

filterContext.HttpContext.Response.AppendHeader("Content-Disposition", string.Format("filename={0}.doc", FileName));

filterContext.HttpContext.Response.ContentType = "application/msword";

base.OnResultExecuted(filterContext);

}

}

使用方式:在一个Action方法上面添加特性:WordDocumentAttribute

?

?

[WordDocument(FileName = "下载文件名称")]

public ActionResult Index()

{

return View();

}

?

?

搞定word导出功能,抛砖引玉,希望能够帮助到大家,也希望有更好实现方式的同学能够一起讨论!!!!!!

ASP.NET MVC 拓展ViewResult实现word文档下载