一、后端
1.Api:
/// <summary>
/// 获取Word文件
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("{infoid}/word")]
public async Task<ActionResult> Word(string infoid)
{
var physicalPath = "xxx";
Dictionary<string, string> keyValues = xxx;
using (FileStream sr = new FileStream(physicalPath + "xxx.docx", FileMode.Open, FileAccess.Read))
{
//读取word模板
XWPFDocument doc = new XWPFDocument(sr);
//关键字替换
doc.ReplaceKey(keyValues);
MemoryStream memoryStream = new MemoryStream();
doc.Write(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
string encodeFilename = HttpUtility.UrlEncode($"VehicleDgTransInfo_{DateTime.Now.ToString("yyyyMMdd")}.docx", Encoding.GetEncoding("UTF-8"));
Response.Headers.Add("Content-Disposition", "attachment; filename=" + encodeFilename);
return new FileStreamResult(memoryStream, "application/octet-stream");//文件流方式,指定文件流对应的ContenType。
}
}
2.XWPFDocumentExtensions.cs:
using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace GuanWei.XPLP.TMIS.Busi.Api.Extensions
{
/// <summary>
/// 扩展方法
/// </summary>
public static class XWPFDocumentExtensions
{
/// <summary>
/// 对象转字段
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
private static Dictionary<string, string> ObjectToDictionary<T>(T obj)
{
Type t = obj.GetType();
PropertyInfo[] pi = t.GetProperties();
Dictionary<string, string> pairs = new Dictionary<string, string>();
foreach (var item in pi)
{
pairs.Add(t.Name + "." + item.Name, item.GetValue(obj).ToString());
}
return pairs;
}
/// <summary>
/// 关键字替换
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="doc"></param>
/// <param name="obj">属性名为key,值为value</param>
/// <param name="func">key值格式化</param>
public static void ReplaceKey<T>(this XWPFDocument doc, T obj, Func<string, string> func = null)
{
doc.ReplaceKey(ObjectToDictionary(obj), func);
}
/// <summary>
/// 段落关键字替换
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="paragraph"></param>
/// <param name="obj">属性名为key,值为value</param>
/// <param name="func">key值格式化</param>
public static void ReplaceKey<T>(this XWPFParagraph paragraph, T obj, Func<string, string> func = null)
{
paragraph.ReplaceKey(ObjectToDictionary(obj), func);
}
/// <summary>
/// 关键字替换
/// </summary>
/// <param name="doc"></param>
/// <param name="paramList">key为被替换的关键字,value为替换后的值</param>
/// <param name="func">key值格式化</param>
public static void ReplaceKey(this XWPFDocument doc, Dictionary<string, string> paramList, Func<string, string> func = null)
{
//遍历段落
foreach (var para in doc.Paragraphs)
{
//段落关键字替换
para.ReplaceKey(paramList, func);
}
//遍历表格
var tables = doc.Tables;
foreach (var table in tables)
{
foreach (var row in table.Rows)
{
foreach (var cell in row.GetTableCells())
{
foreach (var para in cell.Paragraphs)
{
para.ReplaceKey(paramList);
}
}
}
}
}
/// <summary>
/// 段落关键字替换
/// </summary>
/// <param name="paragraph"></param>
/// <param name="paramList">key为被替换的关键字,value为替换后的值</param>
/// <param name="func">key值格式化</param>
public static void ReplaceKey(this XWPFParagraph paragraph, Dictionary<string, string> paramList, Func<string, string> func = null)
{
if (func == null)
{
func = n => "[" + n + "]";
}
string text;
var runs = paragraph.Runs;
foreach (var p in paramList)
{
if (paragraph.Text.Contains("[" + p.Key + "]"))
{
paragraph.ReplaceText(func.Invoke(p.Key), p.Value);
}
}
//for (int i = 0; i < runs.Count; i++)
//{
// var run = runs[i];
// text = run.ToString();
// //Type t = model.GetType();
// //PropertyInfo[] pi = t.GetProperties();
// foreach (var p in paramList)
// {
// if (text.Contains("[" + p.Key + "]"))
// {
// text = text.Replace(func.Invoke(p.Key), p.Value);
// }
// }
// runs[i].SetText(text, 0);
//}
}
/// <summary>
/// 关键字替换为图片(替换为图片时会将图片所在段落的所有字都清空)
/// </summary>
/// <param name="doc"></param>
/// <param name="key">关键字,该方法没有转格式化</param>
/// <param name="pictureData">图片的文件流</param>
/// <param name="pictureType">图片格式默认为png</param>
/// <param name="filename">图片文件名默认为png</param>
/// <param name="width">图片显示宽度</param>
/// <param name="height">图片显示高度</param>
public static void ReplaceImg(this XWPFDocument doc, string key, Stream pictureData, int pictureType = (int)PictureType.PNG, string filename = "1.png", int width = 5000000, int height = 4000000)
{
//遍历段落
foreach (var para in doc.Paragraphs)
{
//段落关键字替换图片
para.ReplaceImg(key, pictureData, pictureType, filename, width, height);
}
}
/// <summary>
/// 段落关键字替换为图片(替换为图片时会将图片所在段落的所有字都清空)
/// </summary>
/// <param name="paragraph"></param>
/// <param name="key">关键字,该方法没有转格式化</param>
/// <param name="pictureData">图片的文件流</param>
/// <param name="pictureType">图片格式默认为png</param>
/// <param name="filename">图片文件名默认为png</param>
/// <param name="width">图片显示宽度</param>
/// <param name="height">图片显示高度</param>
public static void ReplaceImg(this XWPFParagraph paragraph, string key, Stream pictureData, int pictureType = (int)PictureType.PNG, string filename = "1.png", int width = 5000000, int height = 4000000)
{
string text;
var runs = paragraph.Runs;
for (int i = 0; i < runs.Count; i++)
{
var run = runs[i];
text = run.ToString();
if (text.Contains(key))
{
text = "";
runs[i].AddPicture(pictureData, pictureType, filename, width, height);
runs[i].SetText(text, 0);
}
}
}
}
}
二、前端-
1.Axios:
// 获取Word文件
getWord: (id) => {
return request({
url: `${Api}/v1/xxx/${id}/word`,
method: 'get',
responseType: 'blob',
isCustomResponse: true
})
},
重点:responseType: 'blob'
2.下载Word:
xxx.getWord(obj.infoId).then(response => {
var blob = new Blob([response], {type: 'application/msword'}) // 指定格式为vnd.ms-excel
var downloadElement = document.createElement('a')
var href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = 'xxx.docx' // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
})
三、参考:
(1)dotnetcore NPOI:https://github.com/dotnetcore/NPOI
(2)NPOI:https://github.com/tonyqus/npoi