• Dynamics CRM中自定义页面实现附件管理包含下载模板、上传、下载、删除


    前言
    附件使用的Dynamics CRM平台本身的注释表annotation存储,将附件转换成二进制字节流保存到数据库中,因自带的注释在页面中显示附件不够直观,特做了一个单独的附件管理自定义页面,通过CRM自定义按钮打开对话框的方式展示附件列表页面。同时支持下载附件模板,页面为简单的H5+Bootstrap+CSS布局设计,通过ajax调用webAPI接口实现上传、下载、删除等操作,本文一并附上后台接口代码。
    注意:本文中实现上传不支持多文件同时上传,需要多文件同时上传,可找现成的前端文件上传组件,本文中通过input类型'file'传递给后台接口的文件只支持接收一个文件,多文件上传需要修改下对应的后台上传接口,增加参数HttpPostedFileBase[] files,并在处理文件的逻辑改成遍历循环处理即可,其他内容一致。
     
    文件上传方式
    html页面中一个选择文件的input,type类型为'file',再一个上传文件的button按钮,然后做一个表格用来展示已上传的附件列表。选择完文件后,点击上传按钮,获取input中选择的file,js组装new FormData()对象,赋值后台接口所需要的参数,然后ajax调用webapi接口,注意一定要设置processData: false和contentType: false,不然后台接口接收不到文件。后台接口将接受的文件转成流保存到数据库中。
    其他的文件下载和删除就不介绍了,比较简单。
     
    效果图
     
    0
     
     
    代码
     
    自定义按钮打开对话框页面
    复制代码
     1 /**
     2  * 附件管理操作方法
     3  */
     4 function attachment() {
     5     console.log("附件")
     6     if (Xrm.Page.data.entity.getIsDirty()) {
     7         Xrm.Utility.alertDialog("请先保存后再上传附件!")
     8         return
     9     }
    10     let EntityId = commonUtil.delBrackets(Xrm.Page.data.entity.getId())
    11     let EntityName = Xrm.Page.data.entity.getEntityName()
    12 
    13     let params = { 'id': EntityId, 'type': EntityName}
    14 
    15     var DialogOption = new Xrm.DialogOptions
    16     DialogOption.width = 900;
    17     DialogOption.height = 650;
    18     // 参数一:URL,参数二:窗体配置,参数三:Json参数,参数四:--,参数五:--
    19     Xrm.Internal.openDialog("/WebResources/foton_accountchannelaccess_attachment", DialogOption, params, null, function (returnValue) {
    20         console.log('调用成功 返回值:' + returnValue); //这里就可以接收到弹窗上面传过来的数组
    21     });
    22 }
    复制代码
     
    附件管理HTML
      1 DOCTYPE html>
      2 
      3 <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
      4 <head>
      5     <meta charset="utf-8" />
      6     <title>附件管理title>
      7     <script src="foton_Jquery.min.js">script>
      8     <script src="ClientGlobalContext.js.aspx">script>
      9     <script src="foton_kd_base_js">script>
     10     <link href="foton_Newbootstrap.min.css" rel="stylesheet">
     11     <link href="foton_componentsrounded.min.css" rel="stylesheet">
     12     <link href="foton_components.min.css" rel="stylesheet">
     13     <style type="text/css">
     14         .fileinput-button input {
     15             position: static;
     16             opacity: 1;
     17             filter: none;
     18             font-size: inherit;
     19             direction: inherit;
     20         }
     21 
     22         .fileinput-button span {
     23             display: none;
     24         }
     25     style>
     26 head>
     27 <body style="overflow-wrap: break-word;">
     28     <div class="col-md-12" style="width: 100%; height: 100%;">
     29         <div class="portlet box portlet light portlet-fit bordered" style="height: 89%; margin-top: 40px;">
     30             <div class="portlet-body" style="height: 15%;">
     31                 <div class="row">
     32                     <div class="col-md-8">商业计划书新签div>
     33                     <div class="col-md-4" style=" float: right"><label style="color: red;" for="lb_cl1">点击下载模板label>div>
     34                 div>
     35                 <div class="row">
     36                     <div class="col-md-8">商业计划书续签div>
     37                     <div class="col-md-4" style=" float: right"><label style="color: red;" for="lb_cl2">点击下载模板label>div>
     38                 div>
     39                 <div class="row">
     40                     <div class="col-md-8">渠道基本信息评价表div>
     41                     <div class="col-md-4" style=" float: right"><label style="color: red;" for="lb_cl3">点击下载模板label>div>
     42                 div>
     43                 <div class="row">
     44                     <div class="col-md-8">海外网络退出要素确认表div>
     45                     <div class="col-md-4" style=" float: right"><label style="color: red;" for="lb_cl4">点击下载模板label>div>
     46                 div>
     47                 <div class="row">
     48                     <div class="col-md-8">公司简介div>
     49                     <div class="col-md-4"><label style="color: red;">label>div>
     50                 div>
     51             div>
     52             <div class="portlet-title" style="height: 5%;">
     53                 <span>
     54                     <label style="color: red;">请先下载模板,根据模板维护数据后再上传附件!label>
     55                 span>
     56                 
     58                 <div class='row fileupload-buttonbar'>
     59                     <input type='hidden' id='FileName' name='FileName' value='' />
     60                     <input type='hidden' id='UploadType' name='UploadType' value='' />
     61                     <div class='col-lg-7 btnDelete' id='btnFileUploadId' style='margin-left: 30px; float: right'>
     62                         <span class='btn green fileinput-button'>
     63                             <i class='fa fa-plus'>i>
     64                             <span>选择文件span>
     65                             <input type='file' name='fileUpload' id='fileUpload' onchange='document.getElementById("FileName").value = this.value.substr(this.value.lastIndexOf("\\") + 1)'>
     66                         span>
     67                         <button type='button' class='btn blue start' onclick='SaveFiles()'>
     68                             <i class='fa fa-upload'>i>
     69                             <span> 上传文件 span>
     70                         button>
     71                     div>
     72                 div>
     73             div>
     74 
     75             <div class="portlet-body table-scrollable" style="height: 80%; overflow: auto; max-height: 800px; padding: 0 10px">
     76                 <table class="table table-bordered table-hover">
     77                     <thead>
     78                         <tr id="opp">
     79                             <th width="150" style='vertical-align: middle;text-align: center;'> 文件名称 th>
     80                             <th width="150" style='vertical-align: middle;text-align: center;'> 文件类型 th>
     81                             <th width="150" style='vertical-align: middle;text-align: center;'> 创建时间 th>
     82                             <th width="200" style='vertical-align: middle;text-align: center;'> 操作 th>
     83                         tr>
     84                     thead>
     85                     <tbody id="Dataid">tbody>
     86                 table>
     87             div>
     88         div>
     89         div>
     90 
     91 
     92     <script type="text/javascript">
     93         let entityId = window.getDialogArguments().id
     94         let entityName = window.getDialogArguments().type
     95         let queryStr = ""
     96         var apiUrl = ""
     97         var fileObj = document.getElementById("fileUpload")
     98         var outerHTML = fileObj.outerHTML;
     99         //页面加载
    100         $(function () {
    101             setWebAPIURL()
    102             initOnload()
    103             var label1 = $("label[for='lb_cl1']");
    104             label1.on("click", function () {
    105                 console.log("你点击了label1标签");
    106                 downloadTemplate(1)
    107             });
    108             var label2 = $("label[for='lb_cl2']");
    109             label2.on("click", function () {
    110                 console.log("你点击了label2标签");
    111                 downloadTemplate(2)
    112             });
    113             var label3 = $("label[for='lb_cl3']");
    114             label3.on("click", function () {
    115                 console.log("你点击了label3标签");
    116                 downloadTemplate(3)
    117             });  
    118             var label4 = $("label[for='lb_cl4']");
    119             label4.on("click", function () {
    120                 console.log("你点击了label4标签");
    121                 downloadTemplate(4)
    122             });  
    123         })
    124         //设置webapi请求地址
    125         function setWebAPIURL() {
    126             if (Xrm.Page.context.getClientUrl().indexOf("Testf") >= 0)//测试环境
    127                 apiUrl = "http://localhost:50887/"; //测试:http://10.100.56.13:8001/ ,本地:http://localhost:50887/
    128             else if (Xrm.Page.context.getClientUrl().indexOf("hwdms") >= 0)//正式环境
    129                 apiUrl = "https://hwapi.foton.com.cn/";
    130         }
    131         /**
    132          * 页面初始化加载
    133          */
    134         function initOnload() {
    135             //获取客户经销商窗体下的所有附件
    136             queryStr = `/annotations?$select=annotationid,createdon,documentbody,filename,filesize,mimetype,_objectid_value,objecttypecode,subject&$filter=_objectid_value eq ${entityId}&$orderby=createdon desc`
    137             commonUtil.queryWithUrl(queryStr, result => {
    138                 $("#Dataid").empty();
    139                 if (!result.success || !result.data || result.data.length < 1) {
    140                     console.log("当前客户尚未上传附件!")
    141                     return
    142                 }
    143                 console.log(result.data)
    144                 for (var i = 0; i < result.data.length; i++) {
    145                     var html = ""
    146                         + "   ";
    147                     //文件名称
    148                     if (!!result.data[i]["filename"]) {
    149                         html += " " + result.data[i]["filename"] + " ";
    150                     } else {
    151                         html += "";
    152                     }
    153                     //文件类型
    154                     if (!!result.data[i]["mimetype"]) {
    155                         html += " " + result.data[i].filename.substr(result.data[i].filename.lastIndexOf(".") + 1) + " ";
    156                     } else {
    157                         html += "";
    158                     }
    159                     //创建时间
    160                     if (!!result.data[i]["createdon"]) {
    161                         html += " " + result.data[i]["createdon@OData.Community.Display.V1.FormattedValue"] + " ";
    162                     } else {
    163                         html += "";
    164                     }
    165                     //操作
    166                     html += ""
    167                         + " "
    170                         + ""
    171                         + " ";
    172 
    173                     html += "";
    174 
    175                     $("#Dataid").append(html + "
    "); 176 } 177 178 }, false) 179 180 } 181 /* 182 * 调用接口上传文件 183 */ 184 function SaveFiles(callback) { 185 var files = document.getElementById("fileUpload").files[0] 186 if (files.length < 1) { 187 Xrm.Utility.alertDialog("请先选择文件!") 188 return 189 } 190 if (!callback) { 191 overflowLayer.open("上传附件中....", SaveFiles) 192 return 193 } 194 var formFile = new FormData(); 195 formFile.append("entityId", entityId);//实体数据id 196 formFile.append("entityName", entityName);//实体名 197 formFile.append("files", files); //加入文件对象 198 $.ajax({ 199 url: apiUrl + "AccountChannelAccess/SaveAnnotation", 200 type: "post", 201 data: formFile, 202 dataType: 'json', 203 //mimeType: "multipart/form-data", 204 async: true, //使用同步的方式,true为异步方式 205 processData: false, 206 contentType: false, 207 success: function (data, textStatus, xhr) { 208 overflowLayer.close(); 209 if (data.code == 0) { 210 Xrm.Utility.alertDialog(data.msg); 211 } else { 212 Xrm.Utility.alertDialog("上传成功"); 213 //刷新页面 214 initOnload() 215 //清除选择input里已上传的文件 216 fileObj.outerHTML = outerHTML 217 } 218 }, 219 error: function (xhr, textStatus, errorThrown) { 220 Xrm.Utility.alertDialog("请求接口【" + apiUrl + "】失败!请联系管理员!"); 221 overflowLayer.close(); 222 } 223 }); 224 } 225 /** 226 * 删除已上传的文件 227 * @param {any} annotationId 附件id 228 */ 229 function DeleteFile(annotationId) { 230 Xrm.Utility.confirmDialog("您确认要删除此附件吗?", function () { 231 $.ajax({ 232 url: apiUrl + "AccountChannelAccess/DelAnnotation", 233 type: "post", 234 data: { "": annotationId }, 235 dataType: 'json', 236 async: false, //使用同步的方式,true为异步方式 237 success: function (data, textStatus, xhr) { 238 if (data.code == 0) { 239 Xrm.Utility.alertDialog("删除失败!" + data.msg); 240 } 241 Xrm.Utility.alertDialog("删除成功!"); 242 initOnload() 243 }, 244 error: function (xhr, textStatus, errorThrown) { 245 Xrm.Utility.alertDialog("请求接口【" + apiUrl + "】失败!请联系管理员!") 246 } 247 }); 248 }); 249 } 250 /* 251 * 下载文件 252 * @param {any} annotationId 附件id 253 */ 254 function DownloadFile(annotationId) { 255 console.log(annotationId); 256 location.href = apiUrl + 'AccountChannelAccess/DownloadAnnotation?id=' + annotationId; 257 } 258 /** 259 * 下载附件模板 260 * @param {any} type 1商业计划书新签,2商业计划书续签,3渠道基本信息评价表,4海外网络退出要素确认表 261 */ 262 function downloadTemplate(type) { 263 //请求webAPI接口下载模板文件 264 location.href = apiUrl + 'AccountChannelAccess/DownloadFileTemplate?type=' + type; 265 } 266 script> 267 body> 268 html>
    HTML
    WebAPI接口代码
      1 using Microsoft.Xrm.Sdk;
      2 using Microsoft.Xrm.Sdk.Query;
      3 using Newtonsoft.Json;
      4 using NPOI.OpenXml4Net.OPC.Internal;
      5 using System;
      6 using System.Collections.Generic;
      7 using System.Data.Entity.Core.Objects.DataClasses;
      8 using System.IO;
      9 using System.Linq;
     10 using System.Net;
     11 using System.Net.Http;
     12 using System.Net.Http.Headers;
     13 using System.Reflection;
     14 using System.Text;
     15 using System.Threading.Tasks;
     16 using System.Web;
     17 using System.Web.Http;
     18 using ZZ_Common_API.Crm;
     19 using ZZ_Common_API.Models.QDRWModels;
     20 using EntityReference = Microsoft.Xrm.Sdk.EntityReference;
     21 
     22 namespace ZZ_Common_API.Controllers.QDRWControllers
     23 {
     24     /// 
     25     /// 附件相关WebAPI接口
     26     /// 
     27     [RoutePrefix("AccountChannelAccess")]
     28     public class AccountChannelAccessController : ApiController
     29     {
     30         #region 下载模板文件 strat
     31         /// 
     32         /// 下载附件
     33         /// 
     34         /// 1商业计划书新签,2商业计划书续签,3渠道基本信息评价表,4海外网络退出要素确认表
     35         /// 
     36         [Route("DownloadFileTemplate")]
     37         [HttpGet]
     38         public async Task<dynamic> DownloadFileTemplate(int type) 
     39         {
     40             HttpResponseMessage responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
     41             string fileName = string.Empty;
     42             switch (type)
     43             {
     44                 case 1:
     45                     fileName = "附件1:商业计划书新签(可下载模版).pptx";
     46                     break;
     47                 case 2:
     48                     fileName = "附件2:商业计划书续签(可下载模版).pptx";
     49                     break;
     50                 case 3:
     51                     fileName = "附件3:渠道基本信息评价表(可下载模版).docx";
     52                     break;
     53                 case 4:
     54                     fileName = "附件4:海外网络退出要素确认表(可下载模板).docx";
     55                     break;
     56                 default:
     57                     fileName = "附件1:商业计划书新签(可下载模版).pptx";
     58                     break;
     59             }
     60            
     61             var filePath = AppDomain.CurrentDomain.BaseDirectory + @"\Files\Template\" + fileName;
     62             if (!File.Exists(filePath))
     63             {
     64                 return ResponseMessage(new HttpResponseMessage()
     65                 {
     66                     Content =
     67                      new StringContent(JsonConvert.SerializeObject(Json(new { code = 0, msg = $"下载失败,未能找到文件-{fileName}的路径" })),
     68                        Encoding.GetEncoding("UTF-8"), "application/json"),
     69                     StatusCode = HttpStatusCode.NoContent
     70                 });
     71             }
     72             var stream = new FileStream(filePath, FileMode.Open);
     73             responseMessage.Content = new StreamContent(stream);
     74             responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
     75             HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlPathEncode(fileName));
     76             return ResponseMessage(responseMessage);
     77         }
     78         
     79 
     80         #endregion 下载模板文件 end
     81 
     82         #region 上传附件 start
     83         /// 
     84         /// 使用系统的注释Annotation  添加附件
     85         /// 
     86         /// 
     87         [Route("SaveAnnotation")]
     88         [HttpPost]
     89         public object SaveAnnotation()
     90         {
     91             try
     92             {
     93                 HttpFileCollection fileCollection = HttpContext.Current.Request.Files;
     94                 if (fileCollection.Count <= 0)
     95                 {
     96                     return Json(new { code = 0, msg = $"请先选择文件后点击上传" });
     97                 }
     98                 var formData = HttpContext.Current.Request.Form;
     99                 var entityId = formData["entityId"];
    100                 var entityName = formData["entityName"];
    101 
    102                 Guid objId = Guid.Empty;
    103                 if (!Guid.TryParse(entityId, out objId)) //检验实体id是否合法
    104                 {
    105                     return Json(new { code = 0, msg = $"上传失败,entityId是不合法的GUID:{entityId}" });
    106                 }
    107                 HttpPostedFile formFile = fileCollection[0];
    108                 if (formFile.ContentLength > 1048576000)//检查文件大小
    109                 {
    110                     return Json(new { code = 0, msg = $"{formFile.FileName}文件大小不得超过{1048576000 / (1024f * 1024f)}M" });//请求体过大,文件大小超标
    111                 }
    112                 var suffix = Path.GetExtension(formFile.FileName);//提取上传的文件文件后缀
    113                 if (".js;.bat;.exe;.sh".IndexOf(suffix) > 0) //检查文件格式
    114                 {
    115                     return Json(new { code = 0, msg = $"不支持此文件类型-{suffix}" });//类型不正确
    116                 }
    117 
    118                 AnnotationModel model = new AnnotationModel();
    119                 model.Subject = Path.GetFileName(formFile.FileName).Substring(1);
    120                 model.NoteText = "";
    121                 model.ObjectId = objId;
    122                 model.ObjectIdName = entityName;
    123                 model.MimeType = formFile.ContentType;
    124                 model.FileSize = formFile.ContentLength;
    125                 model.FileName = Path.GetFileName(formFile.FileName);
    126                 model.DocumentBody = Convert.ToBase64String(GetFileByte(formFile));
    127                 //保存到Annotation中
    128                 CreateAnnotation(model);
    129 
    130                 return Json(new { code = 1, msg = "上传成功" });
    131             }
    132             catch (Exception ex)
    133             {
    134                 return Json(new { code = 0, msg = $"上传失败 + {ex.Message}" });
    135             }
    136         }
    137         #endregion 上传附件 end
    138 
    139         #region 下载附件 start
    140         /// 
    141         /// 下载附件
    142         /// 
    143         /// 附件id
    144         /// 
    145         [Route("DownloadAnnotation")]
    146         [AcceptVerbs("GET")]
    147         public IHttpActionResult DownloadAnnotation(string id)
    148         {
    149             //通过附件id 找到附件 然后转化附件字节流 填入到响应中
    150             HttpResponseMessage responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
    151             try
    152             {
    153                 if (string.IsNullOrEmpty(id))
    154                 {
    155                     return ResponseMessage(new HttpResponseMessage(HttpStatusCode.Gone));
    156                 }
    157                 Tuple<string, Stream> tuple = GetAnnotationStream(id);
    158                 if (tuple.Item1 == "未能获取到字节流")
    159                 {
    160                     return ResponseMessage(new HttpResponseMessage(HttpStatusCode.Gone));
    161                 }
    162                 responseMessage.Content = new StreamContent(tuple.Item2);
    163                 responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    164                 HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlPathEncode(tuple.Item1));
    165             }
    166             catch (Exception ex)
    167             {
    168                 return ResponseMessage(new HttpResponseMessage()
    169                 {
    170                     Content =
    171                      new StringContent(JsonConvert.SerializeObject(Json(new { code = 0, msg = $"下载失败-{ex.Message}" })),
    172                        Encoding.GetEncoding("UTF-8"), "application/json"),
    173                     StatusCode = HttpStatusCode.NoContent
    174                 });
    175             }
    176             return ResponseMessage(responseMessage);
    177         }
    178         #endregion 下载附件 end
    179 
    180         #region 根据实体id获取实体数据下相关所有附件,打包成zip文件下载 start
    181         /// 
    182         /// 下载实体数据下所有的附件zip
    183         /// 根据实体id获取实体数据下相关所有附件,打包成zip文件下载
    184         /// 
    185         /// 
    186         /// 
    187         [Route("DownloadAnnotationAll")]
    188         [AcceptVerbs("GET")]
    189         public IHttpActionResult DownloadAnnotationAll(string id)
    190         {
    191             HttpResponseMessage responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
    192             try
    193             {
    194                 if (string.IsNullOrEmpty(id))
    195                 {
    196                     return ResponseMessage(new HttpResponseMessage(HttpStatusCode.Gone));
    197                 }
    198                 //通过模块id 找到相关的所有附件 然后将所有的附件打包成zip文件 将zip文件转化字节流 填入到响应流中
    199                 if (string.IsNullOrEmpty(id))
    200                 {
    201                     return ResponseMessage(new HttpResponseMessage(HttpStatusCode.Gone));
    202                 }
    203                 Tuple<string, Stream> tuple = GetAllAnnotationStream(id);
    204                 if (tuple.Item1 == "未能获取到字节流")
    205                 {
    206                     return ResponseMessage(new HttpResponseMessage(HttpStatusCode.Gone));
    207                 }
    208                 responseMessage.Content = new StreamContent(tuple.Item2);
    209                 responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    210                 HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlPathEncode(tuple.Item1));
    211             }
    212             catch (Exception ex)
    213             {
    214                 return ResponseMessage(new HttpResponseMessage()
    215                 {
    216                     Content =
    217                      new StringContent(JsonConvert.SerializeObject(Json(new { code = 0, msg = $"下载失败-{ex.Message}" })),
    218                        Encoding.GetEncoding("UTF-8"), "application/json"),
    219                     StatusCode = HttpStatusCode.NoContent
    220                 });
    221             }
    222             return ResponseMessage(responseMessage);
    223         }
    224 
    225         #endregion 根据实体id获取实体数据下相关所有附件,打包成zip文件下载 end
    226 
    227         #region API专用 删除附件
    228         /// 
    229         /// 删除附件
    230         /// 
    231         /// 附件ids
    232         /// 
    233         [Route("DelAnnotation")]
    234         [HttpPost]
    235         public object DelAnnotation([FromBody] string id)
    236         {
    237             try
    238             {
    239                 if (string.IsNullOrEmpty(id))
    240                 {
    241                     return Json(new { code = 0, msg = $"删除附件时id不能为空" });
    242                 }
    243                 DeleteAnnotation(id);
    244                 return Json(new { code = 1, msg = "删除成功" }); ;
    245             }
    246             catch (Exception ex)
    247             {
    248                 return Json(new { code = 0, msg = $"删除失败:{ex.Message}" });
    249             }
    250         }
    251         #endregion API专用 删除附件
    252 
    253         #region 内部方法 start
    254 
    255         #region 上传附件存到Annotation中 start
    256         /// 
    257         /// 将上传文件对象转化成byte字节流
    258         /// 
    259         /// 上传文件
    260         /// 
    261         private byte[] GetFileByte(HttpPostedFile httpPostedFile)
    262         {
    263             byte[] bytes = new byte[httpPostedFile.ContentLength];
    264             using (BinaryReader reader = new BinaryReader(httpPostedFile.InputStream, Encoding.UTF8))
    265             {
    266                 bytes = reader.ReadBytes(bytes.Length);
    267             }
    268             return bytes;
    269         }
    270         /// 
    271         /// 创建附件数据
    272         /// 
    273         /// 
    274         /// 
    275         private Guid CreateAnnotation(AnnotationModel annotation)
    276         {
    277             Guid guid = Guid.Empty;
    278             IOrganizationService orgService = OrgServiceUtil.Client;
    279             Entity entity = new Entity("annotation");
    280             entity["filename"] = annotation.FileName;
    281             entity["subject"] = annotation.Subject;
    282             entity["mimetype"] = annotation.MimeType;
    283             entity["filesize"] = annotation.FileSize;
    284             entity["documentbody"] = annotation.DocumentBody;
    285             entity["objectid"] = new EntityReference(annotation.ObjectIdName, annotation.ObjectId);
    286             guid = orgService.Create(entity);
    287             return guid;
    288         }
    289         #endregion 上传附件存到Annotation中 end
    290 
    291 
    292         #region 根据附件id获取附件字节流 start
    293         /// 
    294         /// 根据附件id获取附件字节流
    295         /// 
    296         /// annotationid
    297         /// 
    298         public Tuple<string, Stream> GetAnnotationStream(string annotationid)
    299         {
    300             Tuple<string, Stream> rr = new Tuple<string, Stream>("未能获取到字节流", null);
    301             try
    302             {
    303                 IOrganizationService orgService = OrgServiceUtil.Client;
    304                 ColumnSet cols = new ColumnSet("filename", "documentbody");
    305                 Entity entity = orgService.Retrieve("annotation", new Guid(annotationid), cols);
    306                 string documentbody = entity.GetAttributeValue<string>("documentbody");
    307                 string filename = entity.GetAttributeValue<string>("filename");
    308                 byte[] fileContent = Convert.FromBase64String(documentbody);
    309                 Stream fileStream = new MemoryStream(fileContent);
    310                 rr = new Tuple<string, Stream>(filename, fileStream);
    311             }
    312             catch (Exception)
    313             {
    314                 return rr;
    315             }
    316             return rr;
    317         }
    318         #endregion 根据附件id获取附件字节流 end
    319 
    320         #region 根据实体数据id获取所有附件并打包成zip文件,然后转换成字节流 start
    321         /// 
    322         /// 根据实体数据id获取所有附件达成zip包后转换成字节流
    323         /// 
    324         /// 实体数据id
    325         /// 
    326         public Tuple<string, Stream> GetAllAnnotationStream(string entityId)
    327         {
    328             Tuple<string, Stream> rr = new Tuple<string, Stream>("未能获取到字节流", null);
    329             try
    330             {
    331                 IOrganizationService orgService = OrgServiceUtil.Client;
    332                 //1.根据实体数据id查询出所有相关得附件
    333                 var dbList = GetDbFileByEntityId(orgService,new Guid(entityId));
    334                 //2.遍历所有相关得附件 将各个附件流转化存放到内存字典中
    335                 Dictionary<string, byte[]> dic = new Dictionary<string, byte[]>();
    336                 foreach (var cc in dbList)
    337                 {
    338                     string documentbody = cc.GetAttributeValue<string>("documentbody");
    339                     string filename = cc.GetAttributeValue<string>("filename");
    340                     byte[] fileContent = Convert.FromBase64String(documentbody);
    341                     Tuple<string, byte[]> tt = new Tuple<string, byte[]>(filename, fileContent);
    342                     if (tt.Item2 == null)
    343                     {
    344                         continue;
    345                     }
    346                     dic.Add(tt.Item1, tt.Item2);
    347                 }
    348                 if (dic.Count > 0)
    349                 {
    350                     //3.将多个字节流从字典压缩成zip文件并转成一个字节流
    351                     Stream stream = ZipByteHelper.SetbytesToZipStream2(dic);
    352                     rr = new Tuple<string, Stream>("附件.zip", stream);
    353                 }
    354             }
    355             catch (Exception)
    356             {
    357                 return rr;
    358             }
    359             return rr;
    360         }
    361 
    362         private List GetDbFileByEntityId(IOrganizationService orgService,Guid entityId) 
    363         {
    364             var list = new List();
    365             QueryExpression query = new QueryExpression("annotation");
    366             query.ColumnSet = new ColumnSet(true);
    367             query.Criteria.AddCondition(new ConditionExpression("objectid", ConditionOperator.Equal, entityId));
    368             var datas = orgService.RetrieveMultiple(query);
    369             list = datas.Entities.ToArray().ToList();
    370             return list;
    371         }
    372         #endregion 根据实体数据id获取所有附件并打包成zip文件,然后转化称字节流 end
    373 
    374         #region 删除附件 start
    375         /// 
    376         /// 删除附件注释
    377         /// 
    378         /// 附件id
    379         /// 
    380         /// 
    381         public bool DeleteAnnotation(string annotationid)
    382         {
    383             bool result = true;
    384             if (string.IsNullOrEmpty(annotationid))
    385             {
    386                 result = false;
    387             }
    388             IOrganizationService orgService = OrgServiceUtil.Client;
    389             orgService.Delete("annotation", Guid.Parse(annotationid));
    390             return result;
    391         }
    392         #endregion 删除附件 end
    393         #endregion 内部方法 end
    394     }
    395 }
    webAPI接口
    拓展Zip流压缩帮助类
     1 using System;
     2 using System.Collections.Generic;
     3 using System.IO;
     4 using System.Linq;
     5 using System.Web;
     6 
     7 namespace ZZ_Common_API.Utilities
     8 {
     9     /// 
    10     /// 压缩、解压帮助类
    11     /// 
    12     public static class ZipByteHelper
    13     {
    14         /// 
    15         /// 将多个文件流转化成zip文件流
    16         /// 
    17         /// 
    18         /// 
    19         public static Stream SetbytesToZipStream2(Dictionary<string, byte[]> dic)
    20         {
    21             byte[] buffer = new byte[6500];
    22             MemoryStream returnStream = new MemoryStream();
    23             var zipMs = new MemoryStream();
    24             using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipStream = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(zipMs))
    25             {
    26                 zipStream.SetLevel(9);//设置 压缩等级 (9级 500KB 压缩成了96KB)
    27                 foreach (var kv in dic)
    28                 {
    29                     string fileName = kv.Key;
    30                     using (var streamInput = new MemoryStream(kv.Value))
    31                     {
    32                         zipStream.PutNextEntry(new ICSharpCode.SharpZipLib.Zip.ZipEntry(fileName));
    33                         while (true)
    34                         {
    35                             var readCount = streamInput.Read(buffer, 0, buffer.Length);
    36                             if (readCount > 0)
    37                             {
    38                                 zipStream.Write(buffer, 0, readCount);
    39                             }
    40                             else
    41                             {
    42                                 break;
    43                             }
    44                         }
    45                         zipStream.Flush();
    46                     }
    47                 }
    48                 zipStream.Finish();
    49                 zipMs.Position = 0;
    50                 zipMs.CopyTo(returnStream, 5600);
    51             }
    52             returnStream.Position = 0;
    53 
    54             return returnStream;
    55         }
    56     }
    57 }
    ZIP帮助类

     

  • 相关阅读:
    解密C语言选择结构:掌握条件语句与分支逻辑的利器
    IRIS的镜像配置(1)
    用rpm -e --nodeps进行批量删除
    ubuntu小技巧30--23.10桌面版安装钉钉启动报错undefined symbol: FT_Get_Color_Glyph_Layer
    线性表——链表(c语言)
    org.springframework.web.reactive.function.server.ServerResponse设置响应头
    【OpenCV 例程300篇】234. 特征提取之主成分分析(PCA)
    达梦控制台还原报错“管道失败”
    Ompal138+Spartan-6 FPGA开发板硬件数据手册说明书(下)
    06 | 链表(上):如何实现LRU缓存淘汰算法?
  • 原文地址:https://www.cnblogs.com/adingfirstlove/p/17789537.html