不鸣则已

海阔凭鱼跃,天高任鸟飞!

首页 新随笔 联系 订阅 管理

 

本文主要介绍用 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

posted on 2017-07-20 09:58  唐群  阅读(280)  评论(0编辑  收藏  举报