欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET MVC5网站开发添加文章(八)

程序员文章站 2023-12-20 15:50:10
一、添加文章 1、kindeditor富文本编辑器 到官方网站下载最新版本,解压后把代码复制到项目的scripts文件夹下。 2、添加界面的显示。 在artic...

一、添加文章
1、kindeditor富文本编辑器

到官方网站下载最新版本,解压后把代码复制到项目的scripts文件夹下。

ASP.NET MVC5网站开发添加文章(八)

2、添加界面的显示。

在articlecontroller中添加add 方法

/// <summary>
  /// 添加文章
  /// </summary>
  /// <returns>视图页面</returns>
  public actionresult add()
  {
   return view();
  }

右键添加article的强类型视图,代码如下

@section scripts{
 <script type="text/javascript" src="~/scripts/kindeditor/kindeditor-min.js"></script>
 <script type="text/javascript">
  //编辑框
  kindeditor.ready(function (k) {
   window.editor = k.create('#content', {
    height: '500px'
   });
  });
 </script>
}

@model ninesky.models.article
@using (html.beginform())
{ @html.antiforgerytoken()
 <div class="form-horizontal" role="form">
  <h4>添加文章</h4>
  <hr />
  @html.validationsummary(true)
  <div class="form-group">
   <label class="control-label col-sm-2" for="commonmodel_categoryid">栏目</label>
   <div class="col-sm-10">
    <input id="commonmodel_categoryid" name="commonmodel.categoryid" data-options="url:'@url.action("jsontree", "category", new { model="article" })'" class="easyui-combotree" style="height: 34px; width: 280px;" />
      @html.validationmessagefor(model => model.commonmodel.categoryid)</div>
  </div>
  <div class="form-group">
   @html.labelfor(model => model.commonmodel.title, new { @class = "control-label col-sm-2" })
   <div class="col-sm-10">
    @html.textboxfor(model => model.commonmodel.title, new { @class = "form-control" })
    @html.validationmessagefor(model => model.commonmodel.title)
   </div>
  </div>


  <div class="form-group">
   @html.labelfor(model => model.author, new { @class = "control-label col-sm-2" })
   <div class="col-sm-10">
    @html.textboxfor(model => model.author, new { @class = "form-control" })
    @html.validationmessagefor(model => model.author)
   </div>
  </div>

  <div class="form-group">
   @html.labelfor(model => model.source, new { @class = "control-label col-sm-2" })
   <div class="col-sm-10">
    @html.textboxfor(model => model.source, new { @class = "form-control" })
    @html.validationmessagefor(model => model.source)
   </div>
  </div>

  <div class="form-group">
   @html.labelfor(model => model.intro, new { @class = "control-label col-sm-2" })
   <div class="col-sm-10">
    @html.textareafor(model => model.intro, new { @class = "form-control" })
    @html.validationmessagefor(model => model.intro)
   </div>
  </div>

  <div class="form-group">
   @html.labelfor(model => model.content, new { @class = "control-label col-sm-2" })
   <div class="col-sm-10">
    @html.editorfor(model => model.content)
    @html.validationmessagefor(model => model.content)
   </div>
  </div>

  <div class="form-group">
   @html.labelfor(model => model.commonmodel.defaultpicurl, new { @class = "control-label col-sm-2" })
   <div class="col-sm-10">
    <img id="imgpreview" class="thumbnail" src="" />
    @html.hiddenfor(model => model.commonmodel.defaultpicurl)
    <a id="btn_picselect" class="easyui-linkbutton">选择…</a>
    @html.validationmessagefor(model => model.commonmodel.defaultpicurl)
   </div>
  </div>

  <div class="form-group">
   <div class="col-sm-offset-2 col-sm-10">
    <input type="submit" value="添加" class="btn btn-default" />
   </div>
  </div>
 </div>
}


效果如图

ASP.NET MVC5网站开发添加文章(八)

3、后台接受的处理。

[validateinput(false)]
  [httppost]
  [validateantiforgerytoken]
  public actionresult add(article article)
  {
   if(modelstate.isvalid)
   {
    //设置固定值
    article.commonmodel.hits = 0;
    article.commonmodel.inputer = user.identity.name;
    article.commonmodel.model = "article";
    article.commonmodel.releasedate = system.datetime.now;
    article.commonmodel.status = 99;
    article = articleservice.add(article);
    if (article.articleid > 0)
    {
     return view("addsucess", article);
    }
   }
   return view(article);
  }


在做架构的时候dal、bll的base类里有add方法,我们可以直接使用articleservice.add方法添加到数据库

添加文章功能就实现了,但是不能上传附件,不能选择首页图片,不能删除多余的附件。下面就来实现附件功能。

二、附件上传
目标可以上传附件(图片,文件等),文件保存到上传目录中,且数据库中保存相应记录,可以浏览文件列表,未使用的附件可以删除记录。

一、添加附件

在attachmentcontroller添加upload()方法,方法方法把文件写入磁盘中把附件的记录也保存到数据库中,中间会用到读取配置文件,见《.net mvc 网站中配置文件的读写》。

/// <summary>
  /// 上传附件
  /// </summary>
  /// <returns></returns>
  public actionresult upload()
  {
   var _uploadconfig = system.web.configuration.webconfigurationmanager.openwebconfiguration("~").getsection("uploadconfig") as ninesky.models.config.uploadconfig;
   //文件最大限制
   int _maxsize = _uploadconfig.maxsize;
   //保存路径
   string _savepath;
   //文件路径
   string _fileparth = "~/" + _uploadconfig.path + "/";
   //文件名
   string _filename;
   //扩展名
   string _fileext;
   //文件类型
   string _dirname;
   //允许上传的类型
   hashtable exttable = new hashtable();
   exttable.add("image", _uploadconfig.imageext);
   exttable.add("flash", _uploadconfig.fileext);
   exttable.add("media", _uploadconfig.mediaext);
   exttable.add("file", _uploadconfig.fileext);
   //上传的文件
   httppostedfilebase _postfile = request.files["imgfile"];
   if (_postfile == null) return json(new { error = '1', message = "请选择文件" });
   _filename = _postfile.filename;
   _fileext = path.getextension(_filename).tolower();
   //文件类型
   _dirname = request.querystring["dir"];
   if (string.isnullorempty(_dirname))
   {
    _dirname = "image";
   }
   if (!exttable.containskey(_dirname)) return json(new { error = 1, message = "目录类型不存在" });
   //文件大小
   if (_postfile.inputstream == null || _postfile.inputstream.length > _maxsize) return json(new { error = 1, message = "文件大小超过限制" });
   //检查扩展名
   if (string.isnullorempty(_fileext) || array.indexof(((string)exttable[_dirname]).split(','), _fileext.substring(1).tolower()) == -1) return json(new { error = 1, message = "不允许上传此类型的文件。 \n只允许" + ((string)exttable[_dirname]) + "格式。" });
   _fileparth += _dirname + "/" + datetime.now.tostring("yyyy-mm") + "/";
   _savepath = server.mappath(_fileparth);
   //检查上传目录
   if (!directory.exists(_savepath)) directory.createdirectory(_savepath);
   string _newfilename = datetime.now.tostring("yyyymmdd_hhmmss") + _fileext;
    _savepath += _newfilename;
    _fileparth += _newfilename;
   //保存文件
   _postfile.saveas(_savepath);
   //保存数据库记录
   attachmentservice.add(new attachment() { extension = _fileext.substring(1), fileparth = _fileparth, owner = user.identity.name, uploaddate = datetime.now, type = _dirname });
   return json(new { error = 0, url = url.content(_fileparth) });
  }


二、查询附件列表

打开interfaceattachmentservice接口,添加两个方法,都进行了注释比较容易理解,直接上代码。

/// <summary>
  /// 查找附件列表
  /// </summary>
  /// <param name="modelid">公共模型id</param>
  /// <param name="owner">所有者</param>
  /// <param name="type">类型</param>
  /// <returns></returns>
  iqueryable<models.attachment> findlist(nullable<int> modelid, string owner, string type);
  /// <summary>
  /// 查找附件列表
  /// </summary>
  /// <param name="modelid">公共模型id</param>
  /// <param name="owner">所有者</param>
  /// <param name="type">所有者</param>
  /// <param name="withmodelidnull">包含modelid为null的</param>
  /// <returns></returns>
  iqueryable<models.attachment> findlist(int modelid, string owner, string type,bool withmodelidnull);

attachmentservice中写现实代码

public iqueryable<models.attachment> findlist(nullable<int> modelid, string owner, string type)
  {
   var _attachemts = currentrepository.entities.where(a => a.modelid == modelid);
   if (!string.isnullorempty(owner)) _attachemts = _attachemts.where(a => a.owner == owner);
   if (!string.isnullorempty(type)) _attachemts = _attachemts.where(a => a.type == type);
   return _attachemts;
  }

  public iqueryable<models.attachment> findlist(int modelid, string owner, string type, bool withmodelidnull)
  {
   var _attachemts = currentrepository.entities;
   if (withmodelidnull) _attachemts = _attachemts.where(a => a.modelid == modelid || a.modelid == null);
   else _attachemts = _attachemts.where(a => a.modelid == modelid);
   if (!string.isnullorempty(owner)) _attachemts = _attachemts.where(a => a.owner == owner);
   if (!string.isnullorempty(type)) _attachemts = _attachemts.where(a => a.type == type);
   return _attachemts;
  }

由于kindeditor文件管理需要从服务器获取json格式文件列表,在ninesky.web.areas.member.models中单独给列表格式写个视图模型。attachmentmanagerviewmodel

namespace ninesky.web.areas.member.models
{
 /// <summary>
 /// kindeditor文件管理中文件视图模型
 /// <remarks>
 /// 创建:2014.03.09
 /// </remarks>
 /// </summary>
 public class attachmentmanagerviewmodel
 {
  public bool is_dir{get;set;}
  public bool has_file {get;set;}
  public int filesize {get;set;}
  public bool is_photo{get;set;}
  public string filetype{get;set;}
  public string filename{get;set;}
  public string datetime { get; set; }
 }
}

在attachmentcontroller添加返回文件列表的方法filemanagerjson。方法供kindeditor的文件管理器调用

/// <summary>
  /// 附件管理列表
  /// </summary>
  /// <param name="id">公共模型id</param>
  /// <param name="dir">目录(类型)</param>
  /// <returns></returns>
  public actionresult filemanagerjson(int? id ,string dir)
  {
   models.attachmentmanagerviewmodel _attachmentviewmodel;
   iqueryable<attachment> _attachments;
   //id为null,表示是公共模型id为null,此时查询数据库中没有跟模型对应起来的附件列表(以上传,但上传的文章……还未保存)
   if (id == null) _attachments = attachmentservice.findlist(null, user.identity.name, dir);
   //id不为null,返回指定模型id和id为null(新上传的)附件了列表
   else _attachments = attachmentservice.findlist((int)id, user.identity.name, dir, true);
   //循环构造attachmentmanagerviewmodel
   var _attachmentlist = new list<models.attachmentmanagerviewmodel>(_attachments.count());
   foreach(var _attachment in _attachments)
   {
    _attachmentviewmodel = new models.attachmentmanagerviewmodel() { datetime = _attachment.uploaddate.tostring("yyyy-mm-dd hh:mm:ss"), filetype = _attachment.extension, has_file = false, is_dir = false, is_photo = _attachment.type.tolower() == "image" ? true : false, filename = url.content(_attachment.fileparth) };
    fileinfo _fileinfo = new fileinfo(server.mappath(_attachment.fileparth));
    _attachmentviewmodel.filesize = (int)_fileinfo.length;
    _attachmentlist.add(_attachmentviewmodel);
   }
   return json(new { moveup_dir_path = "", current_dir_path = "", current_url = "", total_count = _attachmentlist.count, file_list = _attachmentlist },jsonrequestbehavior.allowget);
  }

3、为图片创建缩略图

把创建缩略图的方法写着common项目中

在ninesky.common的picture类中添加方法

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.drawing;
using system.drawing.drawing2d;
using system.security.cryptography;

namespace ninesky.common
{
 /// <summary>
 /// 图片相关
 /// <remarks>
 /// 创建:2014.02.11
 /// </remarks>
 /// </summary>
 public class picture
 {
  /// <summary>
  /// 创建缩略图
  /// </summary>
  /// <param name="originalpicture">原图地址</param>
  /// <param name="thumbnail">缩略图地址</param>
  /// <param name="width">宽</param>
  /// <param name="height">高</param>
  /// <returns>是否成功</returns>
  public static bool createthumbnail(string originalpicture, string thumbnail, int width, int height)
  {
   //原图
   image _original = image.fromfile(originalpicture);
   // 原图使用区域
   rectanglef _originalarea = new rectanglef();
   //宽高比
   float _ratio = (float)width/height;
   if(_ratio > ((float)_original.width/_original.height))
   {
    _originalarea.x =0;
    _originalarea.width = _original.width;
    _originalarea.height = _originalarea.width / _ratio;
    _originalarea.y = (_original.height - _originalarea.height) / 2;
   }
   else
   {
    _originalarea.y = 0;
    _originalarea.height = _original.height;
    _originalarea.width = _originalarea.height * _ratio;
    _originalarea.x = (_original.width - _originalarea.width) / 2;
   }
   bitmap _bitmap = new bitmap(width, height);
   graphics _graphics = graphics.fromimage(_bitmap);
   //设置图片质量
   _graphics.interpolationmode = interpolationmode.high;
   _graphics.smoothingmode = smoothingmode.highquality;
   //绘制图片
   _graphics.clear(color.transparent);
   _graphics.drawimage(_original, new rectanglef(0, 0, _bitmap.width, _bitmap.height), _originalarea, graphicsunit.pixel);
   //保存
   _bitmap.save(thumbnail);
   _graphics.dispose();
   _original.dispose();
   _bitmap.dispose();
   return true;
  }
 }
}

在attachmentcontroller添加生成缩略图的action

/// <summary>
  /// 创建缩略图
  /// </summary>
  /// <param name="originalpicture">原图地址</param>
  /// <returns>缩略图地址。生成失败返回null</returns>
  public actionresult createthumbnail(string originalpicture)
  {
   //原图为缩略图直接返回其地址
   if (originalpicture.indexof("_s") > 0) return json(originalpicture);
   //缩略图地址
   string _thumbnail = originalpicture.insert(originalpicture.lastindexof('.'), "_s");
   //创建缩略图
   if (common.picture.createthumbnail(server.mappath(originalpicture), server.mappath(_thumbnail), 160, 120))
   {
    //记录保存在数据库中
    attachmentservice.add(new attachment(){ extension= _thumbnail.substring(_thumbnail.lastindexof('.')+1), fileparth="~"+_thumbnail, owner= user.identity.name, type="image", uploaddate= datetime.now});
    return json(_thumbnail);
   }
   return json(null);
  }


三、整合
添加和上传附件都做好了,现在把他们整合到一起,我们就可以上传附件了。

打开add视图,在创建kindeditor位置添加脚本

ASP.NET MVC5网站开发添加文章(八)

现在打开浏览器就可以上传和管理附件了

ASP.NET MVC5网站开发添加文章(八)

ASP.NET MVC5网站开发添加文章(八)

添加文章的最后一个字段是文章的默认首页图片,我希望点击选择按钮,可以在已上传中选择图片,并创建缩略图。

那么在add视图里再弹出一个文件空间让用户选择已上传的文件,用户选择后讲选择的地址发送到服务器创建缩略图,并返回缩略图地址,然后将地址复制给隐藏表单,commonmodel_defaultpicurl,同事复制个<img />的src属性用来显示图片。js代码如下:

//首页图片
   var editor2 = k.editor({
    filemanagerjson: '@url.action("filemanagerjson", "attachment")'
   });
   k('#btn_picselect').click(function () {
    editor2.loadplugin('filemanager', function () {
     editor2.plugin.filemanagerdialog({
      viewtype: 'view',
      dirname: 'image',
      clickfn: function (url, title) {
       var url;
       $.ajax({
        type: "post",
        url: "@url.action("createthumbnail", "attachment")",
        data: { originalpicture: url },
        async: false,
        success: function (data) {
         if (data == null) alert("生成缩略图失败!");
         else {
          k('#commonmodel_defaultpicurl').val(data);
          k('#imgpreview').attr("src", data);
         }
         editor2.hidedialog();
        }
       });
      }
     });
    });
   });


看下效果

ASP.NET MVC5网站开发添加文章(八)

在保存文章的action中删除未使用的附件

ASP.NET MVC5网站开发添加文章(八)

完整的add方法代码

[validateinput(false)]
  [httppost]
  [validateantiforgerytoken]
  public actionresult add(article article)
  {
   if(modelstate.isvalid)
   {
    //设置固定值
    article.commonmodel.hits = 0;
    article.commonmodel.inputer = user.identity.name;
    article.commonmodel.model = "article";
    article.commonmodel.releasedate = system.datetime.now;
    article.commonmodel.status = 99;
    article = articleservice.add(article);
    if (article.articleid > 0)
    {
     //附件处理
     interfaceattachmentservice _attachmentservice = new attachmentservice();
     //查询相关附件
     var _attachments = _attachmentservice.findlist(null, user.identity.name, string.empty).tolist();
     //遍历附件
     foreach(var _att in _attachments)
     {
      var _filepath = url.content(_att.fileparth);
      //文章首页图片或内容中使用了该附件则更改modelid为文章保存后的modelid
      if ((article.commonmodel.defaultpicurl != null && article.commonmodel.defaultpicurl.indexof(_filepath) >= 0) || article.content.indexof(_filepath) > 0)
      {
       _att.modelid = article.modelid;
       _attachmentservice.update(_att);
      }
      //未使用改附件则删除附件和数据库中的记录
      else
      {
       system.io.file.delete(server.mappath(_att.fileparth));
       _attachmentservice.delete(_att);
      }
     }
     return view("addsucess", article);
    }
   }
   return view(article);
  }

单纯添加文章比较简单,复杂点在上传附件,浏览新添加的附件,删除文章中未使用的附件及生成缩略图上。kindeditor还支持批量上传附件,由于批量上传使用的swfupload,在提交时flash没传输cookie到服务器,无法验证用户导致上传失败,暂时无法使用批量上传,希望这篇文章可以对大家的学习有所帮助,大家可以结合小编之前发的文章进行学习,相信一定会有所收获。

上一篇:

下一篇: