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

前言

回顾之前的两篇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.源码下载

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

时间: 2024-10-11 08:42:55

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

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

前言 在上一篇导出文档番外篇中,我们已经熟悉了怎样根据json数据导出word的文档,生成接口文档,而在这一篇,将对上一篇进行完善补充,增加多种导出方式,实现更加完善的导出功能. 回顾 1. 获取Swagger接口文档的Json文件 2. 解析Json文件数据填充到Html的表格中 3.根据生成的html转work文档 功能 开始 根据生成的html转work文档 /// <summary> /// 静态页面转文件 /// </summary> /// <param name

前后端分离ssm配置swagger接口文档

之前配置过springboot,相比ssm要简单很多,现在记录一下ssm的配置 在pom.xml中加入依赖 <!--swagger本身不支持spring mvc的,springfox把swagger包装了一下,让他可以支持springmvc--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <ve

使用Swagger 搭建高可读性ASP.Net WebApi文档

一.前言 在最近一个商城项目中,使用WebApi搭建API项目.但开发过程中,前后端工程师对于沟通接口的使用,是非常耗时的.之前也有用过Swagger构建WebApi文档,但是API文档的可读性并不高.尤其是没有传入参数和传出结果的说明,导致开发人员沟通困难.在园子里看到一篇关于对Swagger优化的文章,有很大的改进.解决了传入参数,API分区域筛选等问题, 非常感谢博主简玄冰. 不过实践之后,发现还有些问题未解决: 接口返回的对象,没有汉化说明 接口授权参数(token)未统一传入 所以,决

.NET平台开源项目速览(4).NET文档生成工具ADB及使用

转载自  http://www.cnblogs.com/asxinyu/p/dotnet_Opensource_project_ADB_CSharpDocument.html 阅读目录 1.ADB介绍 2.ADB生成.NET文档过程 3.资源与代码 很久以前就使用ADB这个工具来生成项目的帮助文档.功能强大,在学习一些开源项目的过程中,官方没有提供CHM帮助文档,所以为了快速的了解项目结构和注释.就生成文档来自己看,非常好用.这也是一个学习方法吧.例如本文在: .NET平台开源项目速览(2)Co

Spring Boot:整合Swagger在线文档

综合概述 spring-boot作为当前最为流行的Java web开发脚手架,越来越多的开发者选择用其来构建企业级的RESTFul API接口.这些接口不但会服务于传统的web端(b/s),也会服务于移动端.在实际开发过程中,这些接口还要提供给开发测试进行相关的白盒测试,那么势必存在如何在多人协作中共享和及时更新API开发接口文档的问题. 假如你已经对传统的wiki文档共享方式所带来的弊端深恶痛绝,那么尝试一下Swagger2 方式,一定会让你有不一样的开发体验. 使用 Swagger 集成文档

基于DevExpress实现对PDF、Word、Excel文档的预览及操作处理

原文:基于DevExpress实现对PDF.Word.Excel文档的预览及操作处理 在一般的管理系统模块里面,越来越多的设计到一些常用文档的上传保存操作,其中如PDF.Word.Excel等文档,有时候是通过分布式的WCF技术实现数据的显示和处理,因此希望直接预览而不需要下载文件,这样能够给我们提供很多的方便.在DevExpress里面,提供了相应的控件来显示和处理这些文档,本文主要介绍如何利用DevExpress的控件实现对PDF.Word.Excel文档的预览和操作处理. 1.PDF的预览

TMS320F2803x系列实时控制 MCU 技术文档

C2000系列实时控制器简介: C2000 生产选择指南 sprufk8.pdf 数据表: 中文板:TMS320F28030/28031/28032/28033/28034/28035 Piccolo 微控制器 (Rev. I)  (zhcs864i.pdf) 英文版:TMS320F28030/28031/28032/28033/28034/28035 Piccolo Microcontrollers  (sprs584j.pdf) 勘误表: TMS320F28030/28031/28032/2

xadmin引入drf-yasg生成Swagger API文档

一.安装drf-yasg: 由于django-rest-swagger已经废弃了 所以引入了drf-yasg pip install drf-yasg 安装install drf-yasg库 https://github.com/axnsan12/drf-yasg Github主页 二.工程的目录结构: demo/settings.py: import os # Build paths inside the project like this: os.path.join(BASE_DIR, ..

Python Django框架实现商城项目源码加设计文档和注释

Python Django框架实现商城项目源码加设计文档和注释 链接:https://pan.baidu.com/s/1yN2iBgx3zmpTkoY8u1LWRg 提取码:lfsx 非常完整的django项目源码,分享给撸友们,不管是学习还是深造,都是可以学习借鉴的!! 原文地址:https://www.cnblogs.com/zyxlovesjy/p/12115491.html