码迷,mamicode.com
首页 > Web开发 > 详细

基于.NetCore3.1搭建项目系列 —— 使用Swagger导出文档 (番外篇)

时间:2020-04-05 18:14:41      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:rar   esc   请求方式   center   如何   text   文档   export   order   

前言

  回顾之前的两篇Swagger做Api接口文档,我们大体上学会了如何在net core3.1的项目基础上,搭建一套自动生产API接口说明文档的框架。

  本来在Swagger的基础上,前后端开发人员在开发生产期间,可以借此进行更加便捷的沟通交流。可是总有些时候,遇到一些难缠的,又不讲道理,偏偏觉得将Swagger文档地址丢给客户会不够正式!死活要一份word文档。

                                 技术图片

  可是这个时候,如果接口数量上百个,甚至更多,一个一个手动输入word,那将是一笔耗时的工作。但却有什么办法可以解决呢?  

  对了,利用Swagge生成的Json文件转换为word文档不就可以了吗?

思路

  1. 获取Swagger接口文档的Json文件

  2. 解析Json文件数据填充到Html的表格中

  3.根据生成的html转work文档

模板

   文档模板

 

URL

/api/Movie/AddMovie

请求方式

Post

参数名

参数类型

是否必填

说明

id

Query

False

影视ID

Name

Query

False

电影名称

Type

Query

False

电影类型

状态码

说明

200

Success

示例

请求参数

 

返回值

 

开始

一、根据Swagger版本获取Json数据

1.通过Swagger源码文件可以看到

技术图片

 可以拿到swagger生成的文档数据,所以我们可以新建一个控制器SwaggerController.cs,

        private readonly SwaggerGenerator _swaggerGenerator;
        public SwaggerController(SwaggerGenerator swaggerGenerator)
        {
            _swaggerGenerator = swaggerGenerator;
        }
        /// <summary>
        /// 导出文件
        /// </summary>
        /// <param name="type">文件类型</param>
        /// <param name="version">版本号V1</param>
        /// <returns></returns>
        [HttpGet]
        public FileResult ExportWord(string type,string version)
        {
            string contenttype = string.Empty;

            var model = _swaggerGenerator.GetSwagger(version); //1. 根据指定版本获取指定版本的json对象。
        }

2. 在Startup.cs文件中,利用net core的ioc容器,注入SwaggerGenerator实例化,这样在后面的调用中可以直接使用这个方法

            services.AddScoped<SwaggerGenerator>(); //注入SwaggerGenerator,后面可以直接使用这个方法

二、文件数据填充到Html的表格中

根据上面获取的model文件数据,这个时候,我们利用Razor文件,结合html的table模板,将数据遍历填充到页面中,生成完整的页面

Html模板

@using Swashbuckle.AspNetCore.Swagger;
<!DOCTYPE html>
<html>
<head>
    <title>Swagger API文档代码文件</title>
    <style type=‘text/css‘>

        table, table td, table th {
            border: 1px solid #000000;
            border-collapse: collapse;
        }

        table {
            table-layout: fixed;
            word-break: break-all;
        }

        tr {
            height: 20px;
            font-size: 12px;
        }
    </style>
</head>
<body>
    <div style=‘width:1000px; margin: 0 auto‘>
        <span><i>Word接口文档</i></span>
        <h1 align="center">@Model.Info.Title</h1>
        <h1 align="center">接口文档 @Model.Info.Version</h1>
        <h4>联系方式</h4>
        <span>作者:@Model.Info.Contact.Name</span>
        <br>
        <a href="mailto:@Model.Info.Contact.Email" rel="noopener noreferrer" class="link">Send email to Xunit.Core</a>
        <br>
        <a href="@Model.Info.Contact.Url" target="_blank" rel="noopener noreferrer" class="link">@Model.Info.Contact.Name - Website</a>
        <br>
        <h3>接口描述</h3>
        <span>@Model.Info.Description</span>
        <br>
        <table border=‘1‘ cellspacing=‘0‘ cellpadding=‘0‘ style="table-layout: fixed; word-break: break-all;border: 1px solid #000000;border-collapse: collapse;" width=‘100%‘>
            <tr style="border: 1px solid #000000;border-collapse: collapse;">
                <td align="center" style="background-color: rgb(84, 127, 177);">说明</td>
                <td></td>
            </tr>
            <tr style="border: 1px solid #000000;border-collapse: collapse;">
                <td align="center" style="background-color: rgb(84, 127, 177);">类型</td>
                <td></td>
            </tr>

        </table>
        @foreach (var item in Model.Paths)
        {
            if (item.Value.Operations != null)
            {
                foreach (var operation in item.Value.Operations)
                {
                    <h3>@operation.Value.Summary</h3>
                    <table border=‘1‘ cellspacing=‘0‘ cellpadding=‘0‘ width=‘100%‘ style="table-layout: fixed; word-break: break-all;border: 1px solid #000000;border-collapse: collapse;">
                        <tr style="background-color: rgb(84, 127, 177);" align="center">
                            <td colspan=‘5‘></td>
                        </tr>
                     
                        <tr style="border: 1px solid #000000;border-collapse: collapse;">
                            <td style="border: 1px solid #000000;border-collapse: collapse;">URL</td>
                            <td colspan=‘4‘>@item.Key</td>
                        </tr>
                        <tr style="border: 1px solid #000000;border-collapse: collapse;">
                            <td style="border: 1px solid #000000;border-collapse: collapse;">请求方式</td>
                            <td colspan=‘4‘>
                                @operation.Key
                            </td>
                        </tr>
                       
                        @if (operation.Value.Parameters != null && operation.Value.Parameters.Count > 0)
                        {
                            <tr style="background-color: rgb(84, 127, 177);" align=‘center‘>
                                <td style="border: 1px solid #000000;border-collapse: collapse;">参数名</td>
                                <td style="border: 1px solid #000000;border-collapse: collapse;">参数类型</td>
                                <td style="border: 1px solid #000000;border-collapse: collapse;">是否必填</td>
                                <td style="border: 1px solid #000000;border-collapse: collapse;" colspan=‘2‘>说明</td>
                            </tr>
                            @foreach (var param in operation.Value.Parameters)
                            {
                                <tr align=‘center‘ style="border: 1px solid #000000;border-collapse: collapse;">
                                    <td style="border: 1px solid #000000;border-collapse: collapse;">@param.Name</td>
                                    <td style="border: 1px solid #000000;border-collapse: collapse;">@param.In</td>
                                    <td style="border: 1px solid #000000;border-collapse: collapse;">@param.Required</td>
                                    <td style="border: 1px solid #000000;border-collapse: collapse;" colspan=‘2‘>@param.Description</td>
                                </tr>
                            }
                        }

                        <tr style="background-color: rgb(84, 127, 177);" align=‘center‘>
                            <td style="border: 1px solid #000000;border-collapse: collapse;">状态码</td>
                            <td style="border: 1px solid #000000;border-collapse: collapse;" colspan=‘4‘>说明</td>
                        </tr>
                        @if (operation.Value.Responses != null && operation.Value.Responses.Count > 0)
                        {
                            foreach (var response in operation.Value.Responses)
                            {
                                <tr align=‘center‘ style="border: 1px solid #000000;border-collapse: collapse;">
                                    <td style="border: 1px solid #000000;border-collapse: collapse;">@response.Key</td>
                                    <td style="border: 1px solid #000000;border-collapse: collapse;" colspan=‘4‘>@response.Value.Description</td>
                                </tr>

                            }
                        }
                        <tr style="background-color: rgb(84, 127, 177);">
                            <td style="border: 1px solid #000000;border-collapse: collapse;" colspan=‘5‘>示例</td>
                        </tr>
                        <tr style="height: 40px;" style="border: 1px solid #000000;border-collapse: collapse;">
                            <td style="background-color: rgb(84, 127, 177);">请求参数</td>
                            <td style="border: 1px solid #000000;border-collapse: collapse;" colspan=‘4‘></td>
                        </tr>
                        <tr style="height: 40px;" style="border: 1px solid #000000;border-collapse: collapse;">
                            <td style="background-color: rgb(84, 127, 177);">返回值</td>
                            <td style="border: 1px solid #000000;border-collapse: collapse;" colspan=‘4‘></td>
                        </tr>
                    </table>
                    <br>
                }

            }
            
        }
    </div>
</body>
</html>

将数据遍历到静态页面中,

        /// <summary>
        /// 将数据遍历静态页面中
        /// </summary>
        /// <param name="templatePath">静态页面地址</param>
        /// <param name="model">获取到的文件数据</param>
        /// <returns></returns>
        public static string GeneritorSwaggerHtml(string templatePath, OpenApiDocument model)
        {
            var template = System.IO.File.ReadAllText(templatePath);
            var result = Engine.Razor.RunCompile(template, "i3yuan", typeof(OpenApiDocument), model);
            return result;
        }

三、根据生成的html转work文档

        /// <summary>
        /// 静态页面转文件
        /// </summary>
        /// <param name="html">静态页面html</param>
        /// <param name="type">文件类型</param>
        /// <param name="contenttype">上下文类型</param>
        /// <returns></returns>
        public Stream SwaggerConversHtml(string html, string type, out string contenttype)
        {
            string fileName = Guid.NewGuid().ToString() + type;
            //文件存放路径
            string webRootPath = _hostingEnvironment.WebRootPath;
            string path = webRootPath + @"\Files\TempFiles\";
            var addrUrl = path + $"{fileName}";
            FileStream fileStream = null;
            var provider = new FileExtensionContentTypeProvider();
            contenttype = provider.Mappings[type];
            try
            {
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                var data = Encoding.Default.GetBytes(html);
                var stream = ByteHelper.BytesToStream(data);
                //创建Document实例
                Document document = new Document();
                //加载HTML文档
                document.LoadFromStream(stream, FileFormat.Html, XHTMLValidationType.None);
                //保存为Word
                document.SaveToFile(addrUrl, FileFormat.Docx);

                document.Close();
                fileStream = File.Open(addrUrl, FileMode.OpenOrCreate);
                var filedata = ByteHelper.StreamToBytes(fileStream);
                var outdata = ByteHelper.BytesToStream(filedata);

                return outdata;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (fileStream != null)
                    fileStream.Close();
                if (File.Exists(addrUrl))
                    File.Delete(addrUrl);//删掉文件
            }
        }
    public class ByteHelper
    {
        public static byte[] StreamToBytes(Stream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            // 设置当前流的位置为流的开始 
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }

        /// 将 byte[] 转成 Stream
        public static Stream BytesToStream(byte[] bytes)
        {
            Stream stream = new MemoryStream(bytes);
            return stream;
        }
    }

四、最终效果

将html转换为word后,我们就可以看到带有 .doc 的效果了!差不多是如下效果

技术图片

总结

  1. 到这基本就结束了,通过简易的几个接口的方式,展示了如何通过将Swagger接口文档生成word文档。可以根据自己的html模板生成各式的word样式文档说明。

  2.写这篇番外主要是因为之前介绍了关于如何使用Swagger生成在线文档,但实际工作中,可能也会遇到这种要各种正式word文档的客户,所以在此分享一些想法和思路,同时希望大家不吝指教。

  3.后续还会不断修改和完善,可以更多的生成不同的文件类型和按需生成不同版本的接口文档,持续更新。。。

  4 .注:搜索关注公众号【DotNet技术谷】--回复【文档生成器】,可获取本篇Swagger转换work文件

  5. 参考资料:Spire.Doc文件 、Swagger开源地址

  6.源码下载

基于.NetCore3.1搭建项目系列 —— 使用Swagger导出文档 (番外篇)

标签:rar   esc   请求方式   center   如何   text   文档   export   order   

原文地址:https://www.cnblogs.com/i3yuan/p/12633768.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!