ASP.NET MVC 文件上传和路径处理总结和Demo下载

目录

文件的上传和路径处理必须解决下面列出的实际问题:

1.重复文件处理

2.单独文件上传

3.编辑器中文件上传

4.处理文章中的图片路径

5.处理上传地址的变化

一.上传文件和重复文件处理

文件处理的原则是:不在数据库中保存文件,只在数据库中保存文件信息(Hash值等)。采取文件的MD5重命名文件在一般情况足够处理文件的重复问题,强迫症倾向则可以考虑将MD5和其他摘要算法结合。

     public static string Save(HttpPostedFileBase file, string path)
        {
            var root = "~/Upload/" + path + "/";
            var phicyPath = HostingEnvironment.MapPath(root);
            Directory.CreateDirectory(phicyPath);
            var fileName = Md5(file.InputStream) + file.FileName.Substring(file.FileName.LastIndexOf(‘.‘));
            file.SaveAs(phicyPath + fileName);
            return fileName;
        }

二.单独文件上传

网站Logo、分类图标等各种场景需要单独文件上传的处理。通过使用UIHintAttribute或自定义继承自UIHintAttribute的特性我们将文件上传的前端逻辑的重复代码消灭,使用统一的视图文件处理。曾经使用过Uplodify和AjaxFileUploader,前者存在flash依赖和cookie问题,后者基本已经过时。此处我们采用KindEditor中的文件上传组件作为演示。非Flash的支持IE6+的方案的核心都是通过iframe方式实现伪AJax上传,核心还是通过html form post到服务器。

    public class UploadModel
    {
        [Display(Name = "图标")]
        [UIHint("Upload")]
        public string Image { get; set; }

        [Display(Name = "简单模式")]
        [UIHint("Editor")]
        [AdditionalMetadata("useSimple", true)]
        public string Text1 { get; set; }

        [Display(Name = "标准模式")]
        [UIHint("Editor")]
        public string Text2 { get; set; }
    }

在我们的实际项目中采取继承UIHintAttribute的方式,其中的path路径指定存储的下级地址,类似的还有DropDownAttribute、EditorAtrribute等等。仅供参考。

    [AttributeUsage(AttributeTargets.Property)]
    public class UploadAttribute : UIHintAttribute, IMetadataAware
    {
        public string Path { get; private set; }

        public UploadAttribute(string path = "")
            : base("Upload")
        {
            this.Path = path;
        }

        public virtual void OnMetadataCreated(ModelMetadata metadata)
        {
            metadata.AdditionalValues.Add("Path", this.Path);
        }
    }

Razor:在Shared中添加EditorTemplates文件夹,新建Upload.cshtml文件。

<script>
    KindEditor.ready(function (K) {
        var editor = K.editor({
            allowFileManager: false,
            allowImageUpload: true,
            formatUploadUrl: false,
            uploadJson: ‘@url‘,
        });
        K(‘#[email protected]‘).click(function () {
            editor.loadPlugin(‘insertfile‘, function () {
                editor.plugin.fileDialog({
                    fileUrl: K(‘#@id‘).val(),
                    clickFn: function (url, title) {
                        K(‘#@id‘).val(url);
                        $(‘#[email protected]‘).attr(‘src‘, url);
                        editor.hideDialog();
                    }
                });
            });
        });
    });
    $(‘#[email protected]‘).click(function () {
        $(‘#@id‘).attr(‘value‘, ‘‘);
        $(‘#[email protected]‘).attr(‘src‘, ‘@Url.Content("~/Images/default.png")‘);
    });
</script>

三.编辑器中的文件上传

编辑器中的文件上传和单独文件上传的主要区别是上传后返回值的处理,编辑器需要将url插入到编辑的位置。编辑器采用过CKeditor和UMeditor,两者都需要我改源代码才能处理路径问题。上传地址和返回值的配置如果不能方便的视图中调整的编辑器,我个人不认为是好编辑器,这就好比一个类库没法扩展和自定义配置一样。仍然采用KindEditor作为演示。Editor.cshtml的主要内容如下:

<script type="text/javascript">
    var editor;
    KindEditor.ready(function (K) {
        editor = K.create(‘textarea[name="@Html.IdForModel()"]‘, {
            resizeType: 1,
            allowPreviewEmoticons: false,
            allowImageUpload: true,
            uploadJson: ‘@UploadManager.UploadUrl‘,
            formatUploadUrl: false,
            allowFileManager: false
            @if(useSimple)
            {
                <text>, items: [
						‘fontname‘, ‘fontsize‘, ‘|‘, ‘forecolor‘, ‘hilitecolor‘, ‘bold‘, ‘italic‘, ‘underline‘,
						‘removeformat‘, ‘|‘, ‘justifyleft‘, ‘justifycenter‘, ‘justifyright‘, ‘insertorderedlist‘,
						‘insertunorderedlist‘, ‘|‘, ‘emoticons‘, ‘image‘, ‘link‘]
                </text>
            }
        });
    });
</script>

四.处理文章中的图片路径

重头戏来了,这个看似问题可以回避,其实真的无法回避。更换目录、域名和端口,使用子域名或其他域名作为图片服务器等等,这些情况让我们必须处理好这个问题,否则日后会浪费更多的时间。这不是小问题,打开支持插入图片的各个网站的编辑器,查看一下图片的路径,大多是绝对url的,又或者只基于根目录的。如果你以产品的形式提供给客户,更不可能要求客户自己挨个替换文章中的路径了。

1.在数据库中不存储文件路径,使用URL路径作为存储。

2.使用html base元素解决相对路径的引用问题。

就是base元素,可能有的人认为这个base可有可无,但在处理图片路径的问题上,没有比base更简洁更优雅的方案了。至少我没有也没找到过。其实可以把全部的静态资源都移除到外部存储,如果你需要。在测试时,我们切换回使用本地存储。

@{
    var baseUrl = UploadManager.UrlPrefix;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />

    <title>@ViewBag.Title</title>
    <base href="@baseUrl" />

    <script src="~/Scripts/jquery-1.11.2.min.js"></script>
    @RenderSection("head",false)
</head>
<body>
    @RenderBody()
</body>
</html>

五.处理上传地址的变化

我们需要独立的图片服务器处理上传或者使用第三方的图片存储服务时,我们的上传地址改变了,如果刚刚提到的图片路径一样,因此我们将上传路径和图片路径都采取配置的方式方便更改,我们就曾经切换到又拍云又切换到自有的服务器。在我的实际使用时配置在数据中使用时采用缓存。为了便于演示我们直接使用配置文件。

首先定义配置文件的处理程序

    public class UploadConfig : IConfigurationSectionHandler
    {
        public object Create(object parent, object configContext, System.Xml.XmlNode section)
        {
            var config = new UploadConfig();
            var urloadUrlNode = section.SelectSingleNode("UploadUrl");
            if (urloadUrlNode != null && urloadUrlNode.Attributes != null && urloadUrlNode.Attributes["href"] != null)
            {
                config.UploadUrl = Convert.ToString(urloadUrlNode.Attributes["href"].Value);
            }

            var urlPrefixNode = section.SelectSingleNode("UrlPrefix");
            if (urlPrefixNode != null && urlPrefixNode.Attributes != null && urlPrefixNode.Attributes["href"] != null)
            {
                config.UrlPrefix = Convert.ToString(urlPrefixNode.Attributes["href"].Value);
            }

            return config;
        }

        public string UploadUrl { get; private set; }

        public string UrlPrefix { get; private set; }
    }

在web.config中配置

 <configSections>
    <section name="UploadConfig" type="SimpleFileManager.UploadConfig, SimpleFileManager" requirePermission="false" />
  </configSections>
  <UploadConfig>
    <UploadUrl href="~/File/Upload/" />
    <UrlPrefix href="~/Upload/" />
 </UploadConfig>

使用UploadMange缓存和管理配置

    public static class UploadManager
    {
        private static string uploadUrl;
        private static string urlPrefix;

        static UploadManager()
        {
            var config = ConfigurationManager.GetSection("UploadConfig") as UploadConfig;
            var url = config != null && !string.IsNullOrEmpty(config.UploadUrl) ? config.UploadUrl : "~/File/Upload";
            uploadUrl = url.StartsWith("~") ? UploadHelper.GetUrlFromVisualPath(url) : url;
            var prefix = config != null && !string.IsNullOrEmpty(config.UrlPrefix) ? config.UrlPrefix : "~/Upload";
            urlPrefix = prefix.StartsWith("~") ? UploadHelper.GetUrlFromVisualPath(prefix) : prefix;
        }

        public static string UploadUrl
        {
            get
            {
                return uploadUrl;
            }
        }

        public static string UrlPrefix
        {
            get
            {
                return urlPrefix;
            }
        }
    }

文件Hash的Md5、返回值的Json处理、完整URL的生成和文件的保存这些具体技术的依赖为了便于演示,统一放置在UploadHelper中,因为这些不是重点。实际应用中可以采取接口隔离并通过IoC注入的方式解耦。

Demo下载:点击下载

时间: 2024-10-29 19:08:40

ASP.NET MVC 文件上传和路径处理总结和Demo下载的相关文章

ASP.NET MVC 文件上传和路径处理

ASP.NET MVC 文件上传和路径处理总结 目录 文件的上传和路径处理必须解决下面列出的实际问题: 1.重复文件处理 2.单独文件上传 3.编辑器中文件上传 4.处理文章中的图片路径 5.处理上传地址的变化 一.上传文件和重复文件处理 文件处理的原则是:不在数据库中保存文件,只在数据库中保存文件信息(Hash值等).采取文件的MD5重命名文件在一般情况足够处理文件的重复问题,强迫症倾向则可以考虑将MD5和其他摘要算法结合. public static string Save(HttpPost

ASP.NET MVC文件上传【转】

最近用到了文件上传功能,下面给出ASP.NET MVC文件上传的一个简单示例: 一.前端代码 @using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new {enctype = "multipart/form-data"})) { <div>文件上传:<input type="file" name="myFile"/&g

ASP.NET MVC 文件上传

如果想要用HTML表单实作文件上传的功能,那么必须在输出的<form>表单标签加上一个enctype属性,且内容必须设定为multipart/form-data,要通过Html.BeginForm辅助方法新增额外的属性必须再加上第四个参数,并传入一个匿名对象即可.如下范例: @using (Html.BeginForm("Upload", "File", FormMethod.Post, new { enctype = "multipart/f

ASP.NET MVC 文件上传和文件下载

1.序言 最近项目中需要用到这个功能点,但是网上下载的时候总是出现乱码.所以趁着这个时间自己整理出了一份,以后需要的时候就直接看自己的博客就行了.已经测试过:在谷歌.火狐.IE等浏览器上都不会出现乱码问题. 2.结果展示 2.1.上传文件成功界面 2.2.下载文件成功界面 3.上传文件代码 3.1.View代码 @model System.Web.HttpContextBase @{ ViewBag.Title = "上传文件"; } <h2>上传文件</h2>

ASP.NET MVC获取上传的路径

刚才有网友问及,怎样获取<input type='file'>的值? Insus.NET测试了一下,在Inetnet Explor之下似乎没有问题,但是FireFox获取到的只是文件名. 在MVC的控制器中,创建一个视图Action,超简单如下: 根据上面创建好的Action,在相应的视图目录下,创建与Action名称相同的视图: 为了看得清楚路径,Insus.NET的input宽度设置尽量长. 使用jQuery来实现.把获取到的路径显示于span tag上. 实时演示:

ASP.NET使用文件上传控件上传图片

ASPX代码 <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xht

基于asp.net 的文件上传和下载~~~转

基于asp.net 的文件上传和下载 摘要: 文件的上传和下载是网络中非常重要的两种应用, 本文介绍了使用asp.net 控件实现文件上传的基本方法.解决了当上传大文件时出现各种问题, 并给出了几种解决方案和技巧.另外, 下载文件用二进制读写的方式实现. 1 引言          文件的上传和下载是网络中非常重要的两种应用.其实现方法主要有FTP 方式和HTTP 方式两种, FTP( File Transfer Protocol)是指文件传输协议, 主要用来在网络上传输文件.这种方式虽说文件传

ASP.NET - 多文件上传,纯代码,不使用插件

解决方案: 前段代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MultiFileUpload.aspx.cs" Inherits="WebApplication1.MultiFileUpload1" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/x

MVC文件上传-使用jQuery.FileUpload和Backload组件实现文件上传

本篇使用客户端jQuery-File-Upload插件和服务端Badkload组件实现多文件异步上传.MVC文件上传相关兄弟篇: 处理文件上传的服务端组件Backload 用于处理文件上传的服务端组件.Backload与客户端文件上传插件(比如jQuery-File-Upload)配合使用,初步形成一个处理文件异步上传的解决方案. □ Badkload的一些功能和特点 ● 零配置:Backload提供默认BackloadDemoController用来处理上传文件请求.如果其它控制器也想拥有"B