一、後端
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