• asp.net Web Api 上传文件


      一、WebApi上使用MultipartFormDataStreamProvider来接收文件时,会自动将文件保存至指定目录下,文件名什么的都是自动生成的。代码如下:

    [HttpPost, Route("savefiles")]
            public async Task<bool> SaveFile(string projectId, string eventId)
            {
                if (!Request.Content.IsMimeMultipartContent())
                {
                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
                } 
                string root = Path.Combine(HostingEnvironment.MapPath(ConfigurationManager.AppSettings["FileStorePath"]), DateTime.Now.ToShortDateString(), projectId);
    
                if (!Directory.Exists(root)) Directory.CreateDirectory(root);
                var provider = new MultipartFormDataStreamProvider(root);
    
                try
                {
                    await Request.Content.ReadAsMultipartAsync(provider);
                    
                }
                catch (Exception ex)
                {
                    WebConfig.LoggerInstance.Error("上传文件出现异常:" + ex.Message);
                }
                return true;
            

    然后在客户端调用如下代码即可

    public async static Task<bool> UploadFile(string url, string fileName)
            {
                HttpClient httpClient = new HttpClient();
    
                var multipartContent = new MultipartFormDataContent();
                using (Stream stream = File.OpenRead(fileName))
                {
                    multipartContent.Add(new StreamContent(stream), "test", "test.txt");
    
                    var responseMessage = await httpClient.PostAsync(url, multipartContent);
                    Task<string> body = responseMessage.Content.ReadAsStringAsync();
                    if ("OK".Equals(responseMessage.StatusCode.ToString())) return true;
                    else return false;
                }
            }

     二、自己保存文件

      首先看下下面的uml 图,图中相关类为Microsoft默认提供的MIME处理类,最后的MultipartFormDataStreamProvider也在前篇博客中有介绍用法,如果要实现开发自定义如何保存文件,按个人最开始的想法是只要继承MultipartFormDataStreamProvider,并重载相关方法即可


    实现代码如下

    /// <summary>
        /// 与MultipartFormDataStreamProvider对应,但不将文件直接存入指定位置,而是需要自己指定数据流如何保存 
        /// </summary>
        public class MultipartFormDataMemoryStreamProvider : MultipartStreamProvider
        {
            private NameValueCollection _formData = new NameValueCollection();
            private Collection<bool> _isFormData = new Collection<bool>();
    
            /// <summary>  
            /// 获取文件对应的HttpContent集合,文件如何读取由实际使用方确定,可以ReadAsByteArrayAsync,也可以ReadAsStreamAsync  
            /// </summary>  
            public Collection<HttpContent> FileContents
            {
                get {
                    if (this._isFormData.Count != this.Contents.Count)//两者总数不一致,认为未执行过必须的Request.Content.ReadAsMultipartAsync(provider)方法  
                    {
                        throw new InvalidOperationException("System.Net.Http.HttpContentMultipartExtensions.ReadAsMultipartAsync must be called first!");
                    }
                    return new Collection<HttpContent>(this.Contents.Where((ct, idx) => !this._isFormData[idx]).ToList());
                }
            }
    
            public NameValueCollection FormData
            {
                get {
                    return this._formData;
                }
            }
            public override async Task ExecutePostProcessingAsync()
            {
                for (var i = 0; i < this.Contents.Count; i++)
                {
                    if (!this._isFormData[i])//非文件  
                    {
                        continue;
                    }
                    var formContent = this.Contents[i];
                    ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition;
                    string formFieldName = UnquoteToken(contentDisposition.Name) ?? string.Empty;
                    string formFieldValue = await formContent.ReadAsStringAsync();
                    this.FormData.Add(formFieldName, formFieldValue);
                }
            }
    
            public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
            {
                if (parent == null)
                {
                    throw new ArgumentNullException("parent");
                }
                if (headers == null)
                {
                    throw new ArgumentNullException("headers");
                }
                ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition;
                if (contentDisposition == null)
                {
                    throw new InvalidOperationException("Content-Disposition is null");
                }
                this._isFormData.Add(string.IsNullOrEmpty(contentDisposition.FileName));
                return new MemoryStream();
            }
    
            /// <summary>  
            /// 复制自 System.Net.Http.FormattingUtilities 下同名方法,因为该类为internal,不能在其它命名空间下被调用  
            /// </summary>  
            /// <param name="token"></param>  
            /// <returns></returns>  
            private static string UnquoteToken(string token)
            {
                if (string.IsNullOrWhiteSpace(token))
                {
                    return token;
                }
                if (token.StartsWith(""", StringComparison.Ordinal) && token.EndsWith(""", StringComparison.Ordinal) && token.Length > 1)
                {
                    return token.Substring(1, token.Length - 2);
                }
                return token;
            }
        }

    然后在在webapi端,使用 

    var provider = new MultipartFormDataMemoryStreamProvider();

    就可以了

     var provider = new MultipartFormDataMemoryStreamProvider();
                try
                {
                    await Request.Content.ReadAsMultipartAsync(provider);
                    foreach (var item in provider.Contents)
                    {
                        var ms = item.ReadAsStreamAsync().Result;
                        using (var br = new BinaryReader(ms))
                        {
                            var data = br.ReadBytes((int)ms.Length);
                            File.WriteAllBytes(root + "/"+eventId+".txt", data);
                        }
                    }
                }
                catch (Exception ex)
                {
                    WebConfig.LoggerInstance.Error("上传文件出现异常:" + ex.Message);
                }
  • 相关阅读:
    【STL】各容器成员对比表
    windows笔记页文件支持的内存映射文件
    windows笔记【内核对象线程同步】线程同步对象速查表
    windows笔记虚拟内存
    windows笔记使用内存映射文件在进程之间共享数据
    svn个人服务端
    解决安装Visual Studio .NET 2003 时FrontPage 2000 WEB 扩展客户端 安装失败
    vc6.0转vs2008连接错误
    Sublime Text插件推荐
    末日了,说出你的梦想、愿望还有遗憾吧。
  • 原文地址:https://www.cnblogs.com/kest/p/8884389.html
Copyright © 2020-2023  润新知