• 文件上传的一些记录(高级)


    本文主要介绍用 asp.net webapi 做文件服务器(包含上传和读取功能)

    1、上文已经介绍了 如何使用 webapi 接受  uploadify 上传的文件(multipart/form-data),

       本文在上文的基础上进行高级开发

    2、限制只有 HandlerAll 接口支持跨域, 删除 webconfig 文件里面所有接口支持跨域的返回头 

    在 HandlerAll 接口开始处返回

    HttpResponseMessage response = Request.CreateResponse();
    response.Headers.Add("Access-Control-Allow-Origin", "*");
    response.Headers.Add("Access-Control-Allow-Methods", "OPTIONS,POST");
    response.Headers.Add("Access-Control-Allow-Headers", "Content-Type,soapaction");

    3、自定义文件保存路径 ,参考这篇文章 http://blog.csdn.net/starfd/article/details/48652871

          说明下主要修改的地方,原来是通过 MultipartFormDataStreamProvider 接的,这个类里面 有个方法 GetStream,是实际处理上传文件的关键

    public class MultipartFormDataStreamProvider : MultipartFileStreamProvider
    {
        // Fields
        private NameValueCollection _formData;
        private Collection<bool> _isFormData;
    
        // Methods
        public MultipartFormDataStreamProvider(string rootPath) : base(rootPath)
        {
            this._formData = HttpValueCollection.Create();
            this._isFormData = new Collection<bool>();
        }
    
        public MultipartFormDataStreamProvider(string rootPath, int bufferSize) : base(rootPath, bufferSize)
        {
            this._formData = HttpValueCollection.Create();
            this._isFormData = new Collection<bool>();
        }
    
        public override Task ExecutePostProcessingAsync() => 
            TaskHelpers.Iterate(base.Contents.Where<HttpContent>(((Func<HttpContent, int, bool>) ((content, index) => this._isFormData[index]))).Select<HttpContent, Task>(delegate (HttpContent formContent) {
                ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition;
                string formFieldName = FormattingUtilities.UnquoteToken(contentDisposition.Name) ?? string.Empty;
                bool runSynchronously = true;
                return formContent.ReadAsStringAsync().Then<string>(delegate (string formFieldValue) {
                    this.FormData.Add(formFieldName, formFieldValue);
                }, new CancellationToken(), runSynchronously);
            }), new CancellationToken(), true);
    
        public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
        {
            if (parent == null)
            {
                throw Error.ArgumentNull("parent");
            }
            if (headers == null)
            {
                throw Error.ArgumentNull("headers");
            }
            ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition;
            if (contentDisposition == null)
            {
                throw Error.InvalidOperation(Resources.MultipartFormDataStreamProviderNoContentDisposition, new object[] { "Content-Disposition" });
            }
            if (!string.IsNullOrEmpty(contentDisposition.FileName))
            {
                this._isFormData.Add(false);
                return base.GetStream(parent, headers);
            }
            this._isFormData.Add(true);
            return new MemoryStream();
        }
    
        // Properties
        public NameValueCollection FormData =>
            this._formData;
    }
    View Code

          再看下他的父类 MultipartFileStreamProvider,一目了然了, MultipartFormDataStreamProvider从名字看就知道是处理整个表单提交里所有正文的,而 MultipartFileStreamProvider 是用来专门处理文件的,因此看文件怎么保存的,到 

          MultipartFileStreamProvider 类里面 GetStream 就能知道怎么处理的了

    public class MultipartFileStreamProvider : MultipartStreamProvider
    {
        // Fields
        private int _bufferSize;
        private Collection<MultipartFileData> _fileData;
        private string _rootPath;
        private const int DefaultBufferSize = 0x1000;
        private const int MinBufferSize = 1;
    
        // Methods
        public MultipartFileStreamProvider(string rootPath) : this(rootPath, 0x1000)
        {
        }
    
        public MultipartFileStreamProvider(string rootPath, int bufferSize)
        {
            this._bufferSize = 0x1000;
            this._fileData = new Collection<MultipartFileData>();
            if (rootPath == null)
            {
                throw Error.ArgumentNull("rootPath");
            }
            if (bufferSize < 1)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("bufferSize", bufferSize, 1);
            }
            this._rootPath = Path.GetFullPath(rootPath);
            this._bufferSize = bufferSize;
        }
    
        public virtual string GetLocalFileName(HttpContentHeaders headers)
        {
            if (headers == null)
            {
                throw Error.ArgumentNull("headers");
            }
            return string.Format(CultureInfo.InvariantCulture, "BodyPart_{0}", new object[] { Guid.NewGuid() });
        }
    
        public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
        {
            string str;
            if (parent == null)
            {
                throw Error.ArgumentNull("parent");
            }
            if (headers == null)
            {
                throw Error.ArgumentNull("headers");
            }
            try
            {
                string localFileName = this.GetLocalFileName(headers);
                str = Path.Combine(this._rootPath, Path.GetFileName(localFileName));
            }
            catch (Exception exception)
            {
                throw Error.InvalidOperation(exception, Resources.MultipartStreamProviderInvalidLocalFileName, new object[0]);
            }
            MultipartFileData item = new MultipartFileData(headers, str);
            this._fileData.Add(item);
            return File.Create(str, this._bufferSize, FileOptions.Asynchronous);
        }
    
        // Properties
        protected int BufferSize =>
            this._bufferSize;
    
        public Collection<MultipartFileData> FileData =>
            this._fileData;
    
        protected string RootPath =>
            this._rootPath;
    }
    View Code

       File.Create(str, this._bufferSize, FileOptions.Asynchronous);  这句是关键,因此只需要在这边不保存就可以了

    4、上传文件后保存带有自定义水印的文件,打水印的原理很简单,就是往原图片快印你的水印图片即可,这里介绍水印图片透明度控制的原理(扩展)

          c# 有个 ImageAttributes 类,参考网上代码 都有个 5*5 的矩阵,矩阵原理 参考 http://tieba.baidu.com/p/1730549463 

    5、控制图片质量(压缩图片) 原理(扩展) 参考 http://www.jb51.net/article/44538.htm、http://www.2cto.com/kf/201007/52380.html

       原理:图片质量通常都是针对 jpg 图片说的,因为 jpg 图片有一个专门控制图片质量的参数,具体的我也没有详细了解

    6、mine 参考手册地址  http://www.w3school.com.cn/media/media_mimeref.asp(非全)

    7、分享一个 base64 对称加密的算法  参考 http://bbs.csdn.net/topics/360042162

    8、base64加密后的字符串含有 + 和 / , 无法 在 get 和 post(http协议) 参数上使用的解决方案

          输出时替换 + => - , / => = , 处理时再替换回来 解密

    9、wepapi 动态接口输出文件无法被 cdn 缓存的解决方案  参考 http://www.cnblogs.com/losbyday/p/5843960.html、http://www.cnblogs.com/softidea/p/5986339.html

          原因: cache-control 控制缓存的优先级比 expires 的高, 通过监视 接口输出 和 静态文件输出 , 可以知道原因 (上面是静态,下面是api接口输出文件)

    10、iis 禁止输出 ETag , 可以提升性能 参考 http://www.cnblogs.com/dudu/p/iis-remove-response-readers.html

  • 相关阅读:
    可惜CodeSmith不直接支持Oracle数据库对象...
    Windows Vista
    关于Web Service ...
    他赚了多少钱?
    关于CodeSmith中模板的属性编辑...
    关于Session超时...
    奇怪的CheckBoxList...
    Devdays 2006 China | 微软开发者日
    第二阶段冲刺第一次会议
    冲刺阶段第一天
  • 原文地址:https://www.cnblogs.com/tq1226112215/p/7209589.html
Copyright © 2020-2023  润新知