文件服务·二开案例·数据库“附件(数据库)”迁移至文件服务器示例代码
本示例演示将附件(数据库)里的物理文件,迁移至附件菜单的附件列表下。
【附件(数据库)】属于常规字段,物理文件存储于数据库表格字段下,单据中可放表头表体,用以上传并存储 UploadWhiteList白名单允许的文件,通过设置允许多选属性可批量上传多个文件,其中这多个文件的文件名、文件大小以及文件内容等信息由 JSONArray 数组对象转 Base64 字符串后直接存储于数据库字段下,数据实体对象的属性类型为字符串类型。
当单据附件上传量过大时,容易造成数据库越来越大,现提供个简单的示例代码用以将“上传文件字段”下的附件迁移至文件服务器中。本例以采购订单单据编号为CGDD000401的单据为例(可根据实际需要自定义自己的过滤条件,建议是分批次进行迁移),对单据头上的“F_FF_FILEUPDATE 附件(数据库)”进行迁移,迁移前需配置并启用文件服务器。
备注:早期版本字段名称为“上传文件字段”,后改名为“附件(数据库)”。
示例代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using Kingdee.BOS; using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Metadata; using Kingdee.BOS.Core.SqlBuilder; using Kingdee.BOS.JSON; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.ServiceHelper; using Kingdee.BOS.Util; using Kingdee.BOS.Core; using Kingdee.BOS.FileServer.Core; using Kingdee.BOS.FileServer.Core.Object; using Kingdee.BOS.FileServer.Core.Object.Enum; using Kingdee.BOS.FileServer.ProxyService; using Kingdee.BOS.Log; namespace Running.Sample.PlugIn.BusinessPlugIn.DynamicForm { /// <summary> /// “上传文件字段”迁移至文件服务器示例代码。 /// </summary> [Description("“上传文件字段”迁移至文件服务器示例代码。")] public class P20190307TransferFileUpdateFieldPlugIn : AbstractDynamicFormPlugIn { private const string BillFormId = "PUR_PurchaseOrder"; //待迁移业务对象唯一标志。 private const string FilterString = "FBILLNO = 'CGDD000401'"; //待迁移单据数据筛选条件。 /// <summary> /// 待迁移单据的单据主键、单据编号以及文件上传字段的字段名。 /// </summary> private readonly string[] _selectFieldKeys = new string[] { "FID", "FBILLNO", "F_FF_FILEUPDATE" }; private FormMetadata _attachmentMetadata; //附件明细元数据对象。 public override void BarItemClick(BarItemClickEventArgs e) { _attachmentMetadata = MetaDataServiceHelper.Load(this.View.Context, "BOS_Attachment") as FormMetadata; Debug.Assert(_attachmentMetadata != null, "_attachmentMetadata != null"); //根据业务对象唯一标志、筛选条件及字段列表,返回待迁移的附件数据,并逐条开始遍历迁移。 QueryBuilderParemeter queryParameter = new QueryBuilderParemeter { FormId = BillFormId, SelectItems = SelectorItemInfo.CreateItems(_selectFieldKeys), //TODO: 自行定义筛选策略,建议分批筛选进行迁移,本次以采购订单单据编号为CGDD000401的单据为例。 FilterClauseWihtKey = FilterString }; DynamicObjectCollection billDynObjCol = QueryServiceHelper.GetDynamicObjectCollection(this.View.Context, queryParameter); foreach (DynamicObject billDynObj in billDynObjCol) { try { //逐条遍历单据数据,进行迁移。 TransferFilesByBillDynObj(billDynObj); } catch (Exception ex) { Logger.Error("TransferFileUpdateField", string.Format("FormId:{0}, FID:{1}的文件迁移失败。", BillFormId, billDynObj["FId"]), ex); /*untrans*/ } } } /// <summary> /// 传入单据实体数据对象,对其下上传文件字段进行迁移。 /// </summary> /// <param name="billDynObj">单据实体数据对象。</param> private void TransferFilesByBillDynObj(DynamicObject billDynObj) { //将文件信息由Base64字符串转为Json数组,因为一个字段值下可能同时挂多个附件,所以需对单个字段值下多个附件逐个遍历上传。 string filesInfo = ObjectUtils.Object2String(billDynObj["F_ff_FileUpdate"]); if (filesInfo.IsNullOrEmptyOrWhiteSpace()) return; JSONArray filesObj = SerializatonUtil.DeserializeFromBase64<JSONArray>(filesInfo); if (filesObj == null || filesObj.Count <= 0) return; //逐个遍历附件,获取文件字节数组并转为内存流,逐个上传至文件服务器。 List<DynamicObject> attachmentDataList = new List<DynamicObject>(); foreach (object fileObj in filesObj) { JSONObject fileJsonObj = (JSONObject)fileObj; if (fileJsonObj["FileName"].IsNullOrEmptyOrWhiteSpace() || fileJsonObj["FileContent"] == null) continue; MemoryStream fileContentStream = new MemoryStream((byte[])fileJsonObj["FileContent"]); TFileInfo tFileInfo = new TFileInfo() { CTX = this.View.Context, FileId = string.Empty, FileName = fileJsonObj["FileName"].ToString(), Last = true, Stream = fileContentStream }; FileUploadResult uploadRes = new UpDownloadService().UploadAttachment(tFileInfo); Logger.Info("TransferFileUpdateField", string.Format("FFileId:{0}, Success:{1}, Msg:{2}", uploadRes.FileId, uploadRes.Success, uploadRes.Message)); if (!uploadRes.Success) continue; //判断上传成功后,收集附件数据,准备批量保存进附件信息表。 attachmentDataList.Add(CollectAttachmentData(billDynObj, uploadRes)); } if (attachmentDataList.Count > 0) BusinessDataServiceHelper.Save(this.View.Context, attachmentDataList.ToArray()); //TODO: 上传成功后是否直接删除数据库文件,需自行定义策略,建议等人工确认附件迁移成功删除历史附件。 } private DynamicObject CollectAttachmentData(DynamicObject billDynObj, FileUploadResult uploadRes) { DynamicObject attachmentData = new DynamicObject(_attachmentMetadata.BusinessInfo.GetDynamicObjectType()); attachmentData["BillType"] = BillFormId; //单据唯一标志。 attachmentData["InterID"] = billDynObj["FId"]; //单据主键。 attachmentData["EntryKey"] = " "; //单据体实体标志,若附件挂单据头上,此处赋值为空即可。 attachmentData["AttachmentName"] = uploadRes.FileName; //文件名。 attachmentData["BillNo"] = billDynObj["FBillNo"]; //单据编号。 attachmentData["AttachmentSize"] = Math.Round(Convert.ToDecimal(uploadRes.FileSize) / 1024, 2); //文件大小,KB为单位。 attachmentData["CreateTime"] = DateTime.Now; //创建时间。 attachmentData["FBillStatus"] = "A"; //单据状态(无效字段)。 attachmentData["CreateMen_Id"] = this.View.Context.UserId; attachmentData["EntryInterID"] = "-1"; //单据体内码。 attachmentData["ExtName"] = Path.GetExtension(uploadRes.FileName); //文件后缀。 attachmentData["FileId"] = uploadRes.FileId; //文件内码。 attachmentData["FileStorage"] = "1"; //文件服务器存储方式。 attachmentData["IsAllowDownLoad"] = 0; //是否禁止下载。 return attachmentData; } } }
文件服务·二开案例·数据库“附件(数据库)”迁移至文件服务器示例代码
本示例演示将附件(数据库)里的物理文件,迁移至附件菜单的附件列表下。【附件(数据库)】属于常规字段,物理文件存储于数据库表格字段下,单...
点击下载文档
本文2024-09-23 03:45:01发表“云星空知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-k3cloud-160862.html
您需要登录后才可以发表评论, 登录登录 或者 注册
最新文档
热门文章