2021年5月6日星期四

文件上传到数据库与下载

基于 FinUICore,实现文件上传到数据库与下载

最终效果如图:

功能实现:
1、表单有两个上传字段,用于上传2个文件;

2、点 "浏览"选择错误的文件,可通过 "删除->重置上传控件" 重置;

3、点"保存并关闭" 保存数据并上传文件;

4、重新打开工序报工,可编辑(已保存的表单数据和文件名会重新显示到页面)。如果已上传文件,则上传控件后的 "下载" 和 "删除->删除" 按钮可用;

5、编辑状态,如上传控件重选文件,"保存并关闭"则会覆盖原文件;

6、点 "删除->删除",可删除文件,不需要点保存即删除(删除前提示确认);删除成功后,控件中的文件名清除、 "下载" 和 "删除->删除" 按钮不可用;

以下介绍实现步骤:

一、创建模型

 

public class R_QC: IKeyID {  [Key]  public int ID { get; set; }  [Display(Name ="PO工序")]  [Required]  public int POProcID { get; set; }  public B03_POProc B03_POProc { get; set; }  [Display(Name ="送检人员")]  public int? SQCID { get; set; }  public User SQC { get; set; }  [Display(Name ="检验人员")]  public int? QCID { get; set; }  public User QC { get; set; }  [Display(Name ="计划检完时间")]  public DateTime? PFinishTime { get; set; }  [Display(Name = "开始检验时间")]  public DateTime? StartTime { get; set; }  [Display(Name = "完成检验时间")]  public DateTime? EndTime { get; set; }  [Display(Name = "检验结果")]  [StringLength(50)]  public string QCResult { get; set; }  [Display(Name = "检验单上传")]  [StringLength(200)]  public string QCReport { get; set; }  [Display(Name = "检验单上传")]  public byte[] QCReportContent { get; set; }  [Display(Name = "拍照留底")]  [StringLength(200)]  public string Photo { get; set; }  [Display(Name = "拍照留底")]  public byte[] PhotoContent { get; set; }  [Display(Name = "备注")]  [StringLength(500)]  public string Remark { get; set; }  [Display(Name = "操作人")]  public int OperatorID { get; set; }  public User Operator { get; set; }  [Display(Name = "状态")]  public int StatusID { get; set; }  public A07_Statu A07_Statu { get; set; }  [Display(Name = "创建时间")]  public DateTime? CreateTime { get; set; } }

 

生成的数据表如下图,其中,2个红框为两个文件记录字段,一个字段记录文件名,一个字段存储文件。

 

二、前端界面设计

1、为了实现"上传控件"、"删除"、"下载" 按钮在同一行,需要为  <f:FormRow > 控件标签增加  ColumnWidths="100%"  属性。

 2、在上传控件后面添加一组菜单按钮,包含  "重置上传控件" 和 "删除"两个菜单按钮。

  • 重置上传控件:点击上传控件的浏览按钮,且选择文件后,可能需要取消选择(不是重选,是取消、不想上传了),可使用该按钮重置、取消选择;方法是为 "重置上传控件" 按钮指定JS,通过 reset() 方法重置。
  • 删除:编辑时,可能需要将已上传文件删除;按钮执行JS,JS弹框提示,点OK后,触发后台事件删除;"删除" 代码见 "四、文件下载与文件删除"

 

@page@model XXX.Pages.WH.R_QCModel@{ ViewData["Title"] = "R_QC"; var F = Html.F();}@section head {}@section body{ <f:Panel ID="Panel1" ShowBorder="false" ShowHeader="false" AutoScroll="true" IsFluid="true" IsViewPort="true">  <Toolbars>   <f:Toolbar ID="Toolbar1" Position="Top" ToolbarAlign="Left">    <Items>     <f:Button ID="btnClose" Icon="SystemClose" Text="关闭">      <Listeners>       <f:Listener Event="click" Handler="F.activeWindow.hide();"></f:Listener>      </Listeners>     </f:Button>     <f:ToolbarSeparator></f:ToolbarSeparator>     <f:Button ID="btnSaveClose" ValidateForms="SimpleForm1" OnClickFields="SimpleForm1" Icon="SystemSaveClose" OnClick="@Url.Handler("BtnSaveClose_Click")" Text="保存后关闭"></f:Button>     <f:ToolbarSeparator></f:ToolbarSeparator>     <f:Button ID="btnFinishClose" ValidateForms="SimpleForm1" OnClickFields="SimpleForm1" IconFont="Check" OnClick="@Url.Handler("BtnSaveClose_Click")" Text="完工关闭"></f:Button>    </Items>   </f:Toolbar>  </Toolbars>  <Items>   <f:Form ID="SimpleForm1" ShowBorder="false" ShowHeader="false" BodyPadding="10" LabelWidth="110">    <Rows>     <f:FormRow>      <Items>       <f:DropDownList For="currentR_QC.SQCID" DataTextField="ChineseName" AutoSelectFirstItem="false" DataSource="@Model.Users"           DataValueField="ID" EmptyText="请选择人员..." EnableEdit="true"></f:DropDownList>              <f:HiddenField ID="currentR_QCID" Text="@Model.currentR_QCID"></f:HiddenField>       <f:HiddenField ID="currentR_QCRProcID" Text="@Model.SelectedNodesID"></f:HiddenField>      </Items>     </f:FormRow>     <f:FormRow>      <Items>       <f:DropDownList For="currentR_QC.QCID" DataTextField="ChineseName" AutoSelectFirstItem="false" DataSource="@Model.Users"           DataValueField="ID" EmptyText="请选择人员..." EnableEdit="true"></f:DropDownList>      </Items>     </f:FormRow>     <f:FormRow>      <Items>       <f:TriggerBox For="currentR_QC.PFinishTime" EmptyText="请选择时间" TriggerIcon="Date" CssClass="dtime"></f:TriggerBox>      </Items>     </f:FormRow>     <f:FormRow>      <Items>       <f:TriggerBox For="currentR_QC.StartTime" EmptyText="请选择时间" TriggerIcon="Date" CssClass="dtime"></f:TriggerBox>      </Items>     </f:FormRow>     <f:FormRow>      <Items>       <f:TriggerBox For="currentR_QC.EndTime" EmptyText="请选择时间" TriggerIcon="Date" CssClass="dtime">       </f:TriggerBox>      </Items>     </f:FormRow>     <f:FormRow>      <Items>       <f:TextBox For="currentR_QC.QCResult"></f:TextBox>      </Items>     </f:FormRow>     <f:FormRow ColumnWidths="100%">      <Items>       <f:FileUpload ID="QCReportContent" Label=检验单上传 AcceptFileTypes="image/*" ButtonIcon="Add" Text="@Model.QCReport"></f:FileUpload>       <f:Button ID="btDelete" Icon="Delete" Text="删除...">        <Menu>         <f:MenuButton ID="rsQCReportContent" Text="重置上传控件" IconFont="Repeat">          <Listeners>           <f:Listener Event="click" Handler="reSetQCReportContent();"></f:Listener>          </Listeners>         </f:MenuButton>         <f:MenuButton ID="mbtDeleteQ" Text="删除" Enabled="@Model.btQCReport" IconFont="Remove">          <Listeners>           <f:Listener Event="click" Handler="reMoveFile('Q');"></f:Listener>          </Listeners>         </f:MenuButton>        </Menu>       </f:Button>       <f:Button ID="btDownloadQCRep" IconFont="Download" Text="下载" Enabled="@Model.btQCReport">        <Listeners>         <f:Listener Event="click" Handler="downLoad('QCReport');"></f:Listener>        </Listeners>       </f:Button>      </Items>     </f:FormRow>     <f:FormRow ColumnWidths="100%">      <Items>       <f:FileUpload ID="PhotoContent" Label="拍照留底" AcceptFileTypes="image/*" ButtonIcon="Add" Text="@Model.Photo"></f:FileUpload>       <f:Button ID="btDelete" Icon="Delete" Text="删除...">        <Menu>         <f:MenuButton ID="rsPhotoContent" Text="重置上传控件" IconFont="Repeat">          <Listeners>           <f:Listener Event="click" Handler="reSetPhotoContent();"></f:Listener>          </Listeners>         </f:MenuButton>         <f:MenuButton ID="mbtDeleteP" Text="删除" Enabled="@Model.btPhoto" IconFont="Remove">          <Listeners>           <f:Listener Event="click" Handler="reMoveFile('P');"></f:Listener>          </Listeners>         </f:MenuButton>        </Menu>               </f:Button>       <f:Button ID="btDownloadPhoto" IconFont="Download" Text="下载" Enabled="@Model.btPhoto">        <Listeners>         <f:Listener Event="click" Handler="downLoad('Photo');" ></f:Listener>        </Listeners>       </f:Button>      </Items>     </f:FormRow>     <f:FormRow>      <Items>       <f:TextArea For="currentR_QC.Remark" AutoGrowHeight="true" EmptyText="最多500字"></f:TextArea>      </Items>     </f:FormRow>    </Rows>   </f:Form>  </Items> </f:Panel>}
@section script { <script src="~/res/third-party/layDate-v5.2.0\laydate\laydate.js" type="text/javascript"></script> <script> function reSetPhotoContent() { var f = F.ui.PhotoContent; f.reset(); } function reSetQCReportContent() { var f = F.ui.QCReportContent; f.reset(); } function reMoveFile(actionType) { F.confirm({ message: '确定删除此文件吗?', target: '_top', ok: function () { // 触发后台事件 F.doPostBack('@Url.Handler("RemoveFile")', 'SimpleForm1',{ actionType: actionType }); } }); } function downLoad(button) { var id = F.ui.currentR_QCID.value; window.location.href = '@Url.Content("~/WH/DownLoad?ID=")' + id + "&button=" + button + "&station=R_QC" ; } F.ready(function () { lay('.dtime').each(function () { laydate.render({ elem: this.getElementsByTagName('input')[0] //this.getElementsByTagName('input')[0] //this.childNodes[1].childNodes[0].childNodes[0] //两种方法均可定位到input元素; , eventElem: this.getElementsByTagName('i')[0] , type: 'datetime' //datetime, , show: false //, trigger: 'click' //, closeStop: '#tbxMyBox-inputEl' , position: 'abolute' //默认值:absolute,绝对定位,始终吸附在绑定元素周围; fixed固定定位,初始吸附在绑定元素周围,不随浏览器滚动条所左右。 , zIndex: 10029 // , theme: 'molv' , calendar: true }); }); }); </script>}

三、数据初始化及上传

1、页面初始化
下载、删除按钮默认不可用;如果记录已存在,上传控件显示文件名,并将下载、删除按钮设置为可用。

public class R_QCModel : BaseAdminModel {  [BindProperty]  public R_QC currentR_QC { get; set; }  public IEnumerable<User> Users { get; set; }    //检验员、送检员下拉列表;  public int SelectedNodesID { get; set; }   //选择的工序ID  public int currentR_QCID { get; set; }  public string Photo { get; set; }       //文件名称  public string QCReport { get; set; }    //文件名称  public bool btPhoto { get; set; }     //下载、删除按钮是否启用;  public bool btQCReport { get; set; }    //下载、删除按钮是否启用;  private readonly long _fileSizeLimit=299999;  private readonly string[] _permittedExtensions = { ".txt",".png" ,".jpeg", ".jpg",".gif" };  public async Task<IActionResult> OnGetAsync(int proc)  {   //下载、删除按钮默认不可用;   btPhoto = false;   btQCReport = false;   // 如果记录已存在,上传控件显示文件名,并将下载、删除按钮设置为可用;   R_QC _currentR_QC = new R_QC();   _currentR_QC = await DB.R_QC.Include(q => q.SQC).Include(q => q.QC).   Where(p => p.POProcID == proc).FirstOrDefaultAsync();   if (_currentR_QC != null)   {    currentR_QC = _currentR_QC;    QCReport=_currentR_QC.QCReport;    Photo= _currentR_QC.Photo;    currentR_QCID = _currentR_QC.ID;    if (_currentR_QC.QCReportContent!=null)    {     btQCReport = true;    }    if (_currentR_QC.PhotoContent!=null)    {     btPhoto = true;    }   }   SelectedNodesID = proc;   Users = await DB.Users.ToListAsync();      return Page();  } }

2、数据、文件上传后端代码

 public async Task<IActionResult> OnPostBtnSaveClose_ClickAsync(string currentR_QCRProcID, string currentR_QCID, List<IFormFile> QCReportContent,List<IFormFile> PhotoContent)  {   //ModelState.Remove("currentR_QC.ID");   if (ModelState.IsValid)   {            var _r = await DB.R_QC.Include(q => q.SQC).Include(q => q.QC).Where(q=>q.ID== Convert.ToInt32(currentR_QCID)).SingleOrDefaultAsync();    //_r 不为空,则更新;    if (_r != null)    {     if (await TryUpdateModelAsync<R_QC>(_r, "currentR_QC"      ,r => r.SQCID      , r => r.QCID      ,r=>r.StartTime      ,r=>r.EndTime      ,r=>r.PFinishTime      ,r=>r.QCResult      ,r=>r.Remark      )      )     {      //文件      foreach (var formFile in QCReportContent)      {       var formFileContent =        await FileHelpers.ProcessFormFile<BufferedMultipleFileUploadDb>(         formFile, ModelState, _permittedExtensions,         _fileSizeLimit);       //// Perform a second check to catch ProcessFormFile method       //// violations. If any validation check fails, return to the       //// page.       if (!ModelState.IsValid)       {        //Alert.Show( "请上传正确格式的文件!");        return UIHelper.Result();       }       _r.QCReportContent = formFileContent;       _r.QCReport = formFile.FileName;      }      foreach (var formFile in PhotoContent)      {       var formFileContent =        await FileHelpers.ProcessFormFile<BufferedMultipleFileUploadDb>(         formFile, ModelState, _permittedExtensions,         _fileSizeLimit);       if (!ModelState.IsValid)       {        //Alert.Show( "请上传正确格式的文件!");        return UIHelper.Result();       }       _r.PhotoContent = formFileContent;       _r.Photo = formFile.FileName;      }     }     }    else //如果记录不存在,则新增记录;    {     currentR_QC.POProcID = Convert.ToInt32(currentR_QCRProcID);     currentR_QC.OperatorID = (int)GetIdentityID();     currentR_QC.CreateTime = DateTime.Now;     currentR_QC.StatusID = 6;     foreach (var formFile in QCReportContent)     {      var formFileContent =        await FileHelpers.ProcessFormFile<BufferedMultipleFileUploadDb>(         formFile, ModelState, _permittedExtensions,         _fileSizeLimit);      if (!ModelState.IsValid)      {       //Alert.Show( "请上传正确格式的文件!");       return UIHelper.Result();      }      currentR_QC.QCReportContent = formFileContent;      currentR_QC.QCReport = formFile.FileName;     }     foreach (var formFile in PhotoContent)     {      var formFileContent =       await FileHelpers.ProcessFormFile<BufferedMultipleFileUploadDb>(        formFile, ModelState, _permittedExtensions,        _fileSizeLimit);      if (!ModelState.IsValid)      {       //Alert.Show( "请上传正确格式的文件!");       return UIHelper.Result();      }      currentR_QC.PhotoContent = formFileContent;      currentR_QC.Photo = formFile.FileName;     }     DB.R_QC.Add(currentR_QC);    }    await DB.SaveChangesAsync();    // 关闭本窗体(触发窗体的关闭事件)    ActiveWindow.HidePostBack();   }   return UIHelper.Result();  }

public class BufferedMultipleFileUploadDb { [Required] [Display(Name = "File")] public List<IFormFile> FormFiles { get; set; } [Display(Name = "Note")] [StringLength(50, MinimumLength = 0)] public string Note { get; set; } }

四、文件下载及文件删除

 1、文件下载后端代码

文件下载,采用跳转页面方式进行。

  • 创建下载页面,页面名称:Download.cshtml
@page@model XXX.Pages.WH.DownloadModel@section body{ <h2>下载出错,文件不存在或已被删除!</h2>}

public class DownloadModel : BaseAdminModel {  public async Task<IActionResult> OnGetAsync(int ID,string station,string button)  {   if (ID != 0)   {    if (station == "R_QC")    {     var requestFile = await DB.R_QC.SingleOrDefaultAsync(q => q.ID == ID);     if (requestFile == null)     {      return Page();     }     if (button == "Photo")     {      if (requestFile.PhotoContent == null)      {       return Page();      }      return File(requestFile.PhotoContent, MediaTypeNames.Application.Octet, requestFile.Photo);     }     if (button == "QCReport")     {      if (requestFile.QCReportContent == null)      {       return Page();      }      return File(requestFile.QCReportContent, MediaTypeNames.Application.Octet, requestFile.QCReport);     }    }    else if (button == "R_QC_Photo")    {    }   }   return Page();  } }

  • 执行下载

2、文件删除后端代码

 //删除已上传的文件  public async Task<IActionResult>OnPostRemoveFileAsync(string actionType,string currentR_QCID)  {   var _r = await DB.R_QC.Where(p => p.ID == Convert.ToInt32(currentR_QCID)).SingleOrDefaultAsync();   if (_r == null)   {    Alert.Show("文件已删除!");    return UIHelper.Result();   }   if (actionType == "Q")   {    _r.QCReportContent = null;    _r.QCReport = null;    //更新前端控件    UIHelper.FileUpload("QCReportContent").Text("");    UIHelper.Button("btDownloadQCRep").Enabled(false);    UIHelper.MenuButton("mbtDeleteQ").Enabled(false);   }   if (actionType == "P")   {    _r.PhotoContent = null;    _r.Photo = null;    //更新前端控件    UIHelper.FileUpload("PhotoContent").Text("");    UIHelper.Button("btDownloadPhoto").Enabled(false);    UIHelper.MenuButton("mbtDeleteP").Enabled(false);   }   await DB.SaveChangesAsync();      return UIHelper.Result();  }

以上是本文全部内容。









原文转载:http://www.shaoqun.com/a/724752.html

跨境电商:https://www.ikjzd.com/

bsci 认证:https://www.ikjzd.com/w/2339

智邦:https://www.ikjzd.com/w/2376


基于FinUICore,实现文件上传到数据库与下载最终效果如图:功能实现:1、表单有两个上传字段,用于上传2个文件;2、点"浏览"选择错误的文件,可通过"删除->重置上传控件"重置;3、点"保存并关闭"保存数据并上传文件;4、重新打开工序报工,可编辑(已保存的表单数据和文件名会重新显示到页面)。如果已上传文件,则上传控件后的"下载"和"删除->删除"按钮可用;5、编辑状态,如上传控件重
hemingway:https://www.ikjzd.com/w/2344
垂直电商:https://www.ikjzd.com/w/1450
商标抢注:https://www.ikjzd.com/w/1053
口述:同居3年 我被折磨得身心俱疲同居怀孕人流:http://lady.shaoqun.com/m/a/27795.html
口述:90后女同事在宾馆摸我下半身90后出轨风骚:http://lady.shaoqun.com/m/a/29438.html
老公嫌我叫床声大差点捂死我:http://lady.shaoqun.com/m/a/270837.html

没有评论:

发表评论