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

ASP.NET Web API 应用教程(一) ——数据流使用

程序员文章站 2023-01-21 21:26:31
  相信已经有很多文章来介绍asp.net web api 技术,本系列文章主要介绍如何使用数据流,https,以及可扩展的web api 方面的技术,系列...


ASP.NET Web API 应用教程(一) ——数据流使用

 

相信已经有很多文章来介绍asp.net web api 技术,本系列文章主要介绍如何使用数据流,https,以及可扩展的web api 方面的技术,系列文章主要有三篇内容。

主要内容如下:

i 数据流

ii 使用https

iii 可扩展的web api 文档

 

项目环境要求

  • vs 2012(sp4)及以上,
  • .net 框架4.5.1
  • nuget包,可在packages.config 文件中查寻

    本文涉及的知识点

    1. actionfilter
    2. authorizationfilter
    3. delegatehandler
    4. different web api routing 属性
    5. mediatypeformatter
    6. owin
    7. self hosting
    8. web api 文档及可扩展功能

      .net 框架

      1. async/await
      2. .net reflection
      3. serialization
      4. asp.net web api/mvc error handling
      5. iis ,https 及certificate
      6. 设计准则及技术

        前言

        ASP.NET Web API 应用教程(一) ——数据流使用

         

        自从asp.net mvc 4之后.net 框架开始支持asp.net web api ,asp.net web api 基于http 协议建立的,是构建 restful 服务和处理数据的理想平台,旨在使用http 技术实现对多平台的支持。

        asp.net web api 以request-response 的消息转换模式为主,客户端向服务器发送请求,服务器端响应客户端请求。响应可同步或异步。

        个人认为使用web api创建应用需要注意的三个关键点:

        • 采用服务及方法满足的目标
        • 每个方法的输入,如请求
        • 每个方法的输出,如响应

          通常情况下,asp.net web api 定义method语法与http方法一一对应的,如自定义方法名 getpysicians(),则与http中get 方法匹配。下图是常用匹配表。

           

          ASP.NET Web API 应用教程(一) ——数据流使用


          但是此方法在很多情况下,并不实用,假如你想在单个api controller 类中定义多个get 或post 方法,在这种情况下,需要定义包含action 的路径,将action 作为uri 的一部分。以下是配置代码:

             1:  public static void register(httpconfiguration config)
             2:  {
             3:      // web api configuration and services
             4:      // web api routes
             5:       config.maphttpattributeroutes();
             6:      
             7:       config.routes.maphttproute(name: physicianapi,
             8:                  routetemplate: {controller}/{action}/{id},
             9:                  defaults: new { id = routeparameter.optional });
            10:  }

          但是此方法不足以应对所有情况,如果想实现从*仓库删除文件,并且想调用同一个方法来获取文件,这种情况下,web api 框架需要伪装get 及delete对应的http 方法属性。如图所示:

          ASP.NET Web API 应用教程(一) ——数据流使用

          removefile 方法可被delete(httpdelete) 或 get(httpget)方法同时调用,从某种程度来说,http 方法使开发人员命名 api“方法”变得简单而标准。

          web api框架也提供了一些其他功能来处理路径方面的问题,与mvc 的路径处理方法相似。因此可定义不同类型的action方法。

          数据流

          网络app 最常见的执行操作就是获取数据流。asp.net web api 能够处理客户端与服务器端传输的重量级的数据流,数据流可来源于目录文件,也可是中的二进制文件。本文主要介绍两种方法“download”和“upload”实现数据流相关的功能,download是从服务器下载数据操作,而upload则是上传数据到服务器。

          相关项目

          • webapidatastreaming
          • webapiclient
          • pocolibrary

            在对代码解释之前,首先来了解如何配置iis(7.5)和web api 服务web.config 文件。

            1. 保证downloads/uploads 涉及的文件具有读写权限。

            2. 保证有足够容量的内容或因*空间处理大文件。

            3. 如果文件较大

            a. 配置web.config 文件时,保证 maxrequestlength 时响应时间 executiontimeout 合理。具体的值主要依赖于数据大小,允许一次性上传的最大数据为2 gb

            ASP.NET Web API 应用教程(一) ——数据流使用

            b. 保证 maxallowedcontentlength 在requestfiltering部分配置下正确设置,默认值为30mb,最大值4gb

            ASP.NET Web API 应用教程(一) ——数据流使用

            一旦完成预先配置,那么创建数据流服务就非常简单了,首先 需要定义文件流“apicontroller”,如下:

               1:  /// 
               2:  /// file streaming api
               3:  /// 
               4:  [routeprefix(filestreaming)]
               5:  [requestmodelvalidator]
               6:  public class streamfilescontroller : apicontroller
               7:  {
               8:      /// 
               9:      /// get file meta data
              10:      /// 
              11:      ///filename value
              12:      /// filemeta data response.
              13:      [route(getfilemetadata)]
              14:      public httpresponsemessage getfilemetadata(string filename)
              15:      {
              16:          // .........................................
              17:          // full code available in the source control
              18:          // .........................................
              19:   
              20:      }
              21:   
              22:      /// 
              23:      /// search file and return its meta data in all download directories
              24:      /// 
              25:      ///filename value
              26:      /// list of file meta datas response
              27:      [httpget]
              28:      [route(searchfileindownloaddirectory)]
              29:      public httpresponsemessage searchfileindownloaddirectory(string filename)
              30:      {
              31:          // .........................................
              32:          // full code available in the source control
              33:          // .........................................
              34:      }
              35:   
              36:      /// 
              37:      /// asynchronous download file
              38:      /// 
              39:      ///filename value
              40:      /// tasked file stream response
              41:      [route(downloadasync)]
              42:      [httpget]
              43:      public async task downloadfileasync(string filename)
              44:      {
              45:          // .........................................
              46:          // full code available in the source control
              47:          // .........................................
              48:      }
              49:   
              50:      /// 
              51:      /// download file
              52:      /// 
              53:      ///filename value
              54:      /// file stream response
              55:      [route(download)]
              56:      [httpget]
              57:      public httpresponsemessage downloadfile(string filename)
              58:      {
              59:          // .........................................
              60:          // full code available in the source control
              61:          // .........................................
              62:      }
              63:   
              64:      /// 
              65:      /// upload file(s)
              66:      /// 
              67:      ///an indicator to overwrite a file if it exist in the server
              68:      /// message response
              69:      [route(upload)]
              70:      [httppost]
              71:      public httpresponsemessage uploadfile(bool overwrite)
              72:      {
              73:          // .........................................
              74:          // full code available in the source control
              75:          // .........................................
              76:      }
              77:   
              78:      /// 
              79:      /// asynchronous upload file
              80:      /// 
              81:      ///an indicator to overwrite a file if it exist in the server
              82:      /// tasked message response
              83:      [route(uploadasync)]
              84:      [httppost]
              85:      public async task uploadfileasync(bool overwrite)
              86:      {
              87:          // .........................................
              88:          // full code available in the source control
              89:          // .........................................
              90:      }
              91:  }

            download 服务方法首先需要确认请求的文件是否存在,如果未找到,则返回错误提示“file is not found”,如果找到此文件,内容则转换为字节附加到响应对象,为“application/octet-stream” mimi 内容类型。

               1:  /// 
               2:  /// download file
               3:  /// 
               4:  ///filename value
               5:  /// file stream response
               6:  [route(download)]
               7:  [httpget]
               8:  public httpresponsemessage downloadfile(string filename)
               9:  {
              10:      httpresponsemessage response = request.createresponse();
              11:      filemetadata metadata = new filemetadata();
              12:      try
              13:      {
              14:          string filepath = path.combine(this.getdownloadpath(), @, filename);
              15:          fileinfo fileinfo = new fileinfo(filepath);
              16:   
              17:          if (!fileinfo.exists)
              18:          {
              19:              metadata.fileresponsemessage.isexists = false;
              20:              metadata.fileresponsemessage.content = string.format({0} file is not found !, filename);
              21:              response = request.createresponse(httpstatuscode.notfound, metadata, new mediatypeheadervalue(text/json));
              22:          }
              23:          else
              24:          {
              25:              response.headers.acceptranges.add(bytes);
              26:              response.statuscode = httpstatuscode.ok;
              27:              response.content = new streamcontent(fileinfo.readstream());
              28:              response.content.headers.contentdisposition = new contentdispositionheadervalue(attachment);
              29:              response.content.headers.contentdisposition.filename = filename;
              30:              response.content.headers.contenttype = new mediatypeheadervalue(application/octet-stream);
              31:              response.content.headers.contentlength = fileinfo.length;
              32:          }
              33:      }
              34:      catch (exception exception)
              35:      {
              36:          // log exception and return gracefully
              37:          metadata = new filemetadata();
              38:          metadata.fileresponsemessage.content = processexception(exception);
              39:          response = request.createresponse(httpstatuscode.internalservererror, metadata, new mediatypeheadervalue(text/json));
              40:      }
              41:      return response;
              42:  }

            upload服务方法则会在multipart/form-data mimi 内容类型执行,首先会检测http 请求的内容类型是否是多主体,如果是,则对比内容长度是否超过最大尺寸,如果没有超过,则开始上传内容,当操作完成之后,则提示相应的信息。

            代码片段如下:

               1:  /// 
               2:  /// upload file(s)
               3:  /// 
               4:  ///an indicator to overwrite a file if it exist in the server.
               5:  /// message response
               6:  [route(upload)]
               7:  [httppost]
               8:  public httpresponsemessage uploadfile(bool overwrite)
               9:  {
              10:      httpresponsemessage response = request.createresponse();
              11:      list fileresponsemessages = new list();
              12:      fileresponsemessage fileresponsemessage = new fileresponsemessage { isexists = false };
              13:   
              14:      try
              15:      {
              16:          if (!request.content.ismimemultipartcontent())
              17:          {
              18:              fileresponsemessage.content = upload data request is not valid !;
              19:              fileresponsemessages.add(fileresponsemessage);
              20:              response = request.createresponse(httpstatuscode.unsupportedmediatype, fileresponsemessages, new mediatypeheadervalue(text/json));
              21:          }
              22:   
              23:          else
              24:          {
              25:              response = processuploadrequest(overwrite);
              26:          }
              27:      }
              28:      catch (exception exception)
              29:      {
              30:          // log exception and return gracefully
              31:          fileresponsemessage = new fileresponsemessage { isexists = false };
              32:          fileresponsemessage.content = processexception(exception);
              33:          fileresponsemessages.add(fileresponsemessage);
              34:          response = request.createresponse(httpstatuscode.internalservererror, fileresponsemessages, new mediatypeheadervalue(text/json));
              35:   
              36:      }
              37:      return response;
              38:  }
              39:   
              40:  /// 
              41:  /// asynchronous upload file
              42:  /// 
              43:  ///an indicator to overwrite a file if it exist in the server.
              44:  /// tasked message response
              45:  [route(uploadasync)]
              46:  [httppost]
              47:  public async task uploadfileasync(bool overwrite)
              48:  {
              49:      return await new taskfactory().startnew(
              50:         () =>
              51:         {
              52:             return uploadfile(overwrite);
              53:         });
              54:  }
              55:   
              56:  /// 
              57:  /// process upload request in the server
              58:  ///  
              59:  ///an indicator to overwrite a file if it exist in the server.
              60:  /// list of message object
              61:  private httpresponsemessage processuploadrequest(bool overwrite)
              62:  {
              63:      // .........................................
              64:      // full code available in the source control
              65:      // .........................................
              66:  }

            调用download 及 upload 文件方法是控制台应用,app 假定文件流服务通过httpclient和相关类。基本下载文件代码,创建下载http 请求对象。

               1:  /// 
               2:  /// download file
               3:  /// 
               4:  /// awaitable task object
               5:  private static async task downloadfile()
               6:  {
               7:      console.foregroundcolor = consolecolor.green;
               8:      console.writeline(please specify file name  with extension and press enter :- );
               9:      string filename = console.readline();
              10:      string localdownloadpath = string.concat(@c:, filename); // the path can be configurable
              11:      bool overwrite = true;
              12:      string actionurl = string.concat(downloadasync?filename=, filename);
              13:   
              14:      try
              15:      {
              16:          console.writeline(string.format(start downloading @ {0}, {1} time ,
              17:              datetime.now.tolongdatestring(),
              18:              datetime.now.tolongtimestring()));
              19:   
              20:   
              21:          using (httpclient httpclient = new httpclient())
              22:          {
              23:              httpclient.baseaddress = basestreamingurl;
              24:              httprequestmessage request = new httprequestmessage(httpmethod.get, actionurl);
              25:   
              26:              await httpclient.sendasync(request, httpcompletionoption.responseheadersread).
              27:                  continuewith((response)
              28:                      =>
              29:                  {
              30:                      console.writeline();
              31:                      try
              32:                      {
              33:                          processdownloadresponse(localdownloadpath, overwrite, response);
              34:                      }
              35:                      catch (aggregateexception aggregateexception)
              36:                      {
              37:                          console.foregroundcolor = consolecolor.red;
              38:                          console.writeline(string.format(exception : , aggregateexception));
              39:                      }
              40:                  });
              41:          }
              42:      }
              43:      catch (exception ex)
              44:      {
              45:          console.foregroundcolor = consolecolor.red;
              46:          console.writeline(ex.message);
              47:      }
              48:  }
              49:   
              50:   
              51:  /// 
              52:  /// process download response object
              53:  /// 
              54:  ///local download file path
              55:  ///an indicator to overwrite a file if it exist in the client.
              56:  ///awaitable httpresponsemessage task value
              57:  private static void processdownloadresponse(string localdownloadfilepath, bool overwrite,
              58:      task response)
              59:  {
              60:      if (response.result.issuccessstatuscode)
              61:      {
              62:          response.result.content.downloadfile(localdownloadfilepath, overwrite).
              63:              continuewith((downloadmessage)
              64:                  =>
              65:              {
              66:                  console.foregroundcolor = consolecolor.green;
              67:                  console.writeline(downloadmessage.tryresult());
              68:              });
              69:      }
              70:      else
              71:      {
              72:          processfailresponse(response);
              73:      }
              74:  }

             

            注意上述代码中httpclient 对象发送请求,并等待响应发送header内容(httpcompletionoption.responseheadersread )。而不是发送全部的响应内容文件。一旦response header 被读,则执行验证,一旦验证成功,则执行下载方法。

            以下代码调用upload 文件流,与下载方法类似,创建多主体表单数据,并发送给服务器端。

               1:  /// 
               2:  /// upload file
               3:  /// 
               4:  /// awaitable task object
               5:  private static async task uploadfile()
               6:  {
               7:      try
               8:      {
               9:          string uploadrequesturi = uploadasync?overwrite=true;
              10:   
              11:          multipartformdatacontent formdatacontent = new multipartformdatacontent();
              12:   
              13:          // validate the file and add to multipartformdatacontent object
              14:          formdatacontent.adduploadfile(@c:
            ophoto.png);
              15:          formdatacontent.adduploadfile(@c:readme.txt);
              16:   
              17:          if (!formdatacontent.hascontent()) // no files found to be uploaded
              18:          {
              19:              console.foregroundcolor = consolecolor.red;
              20:              console.write(formdatacontent.getuploadfileerrormesage());
              21:              return;
              22:          }
              23:          else
              24:          {
              25:              string uploaderrormessage = formdatacontent.getuploadfileerrormesage();
              26:              if (!string.isnullorwhitespace(uploaderrormessage)) // some files couldn't be found
              27:              {
              28:                  console.foregroundcolor = consolecolor.red;
              29:                  console.write(uploaderrormessage);
              30:              }
              31:   
              32:              httprequestmessage request = new httprequestmessage(httpmethod.post, uploadrequesturi);
              33:              request.content = formdatacontent;
              34:   
              35:              using (httpclient httpclient = new httpclient())
              36:              {
              37:                  console.foregroundcolor = consolecolor.green;
              38:                  console.writeline(string.format(start uploading @ {0}, {1} time ,
              39:                  datetime.now.tolongdatestring(),
              40:                  datetime.now.tolongtimestring()));
              41:   
              42:                  httpclient.baseaddress = basestreamingurl;
              43:                  await httpclient.sendasync(request).
              44:                        continuewith((response)
              45:                            =>
              46:                            {
              47:                                try
              48:                                {
              49:                                    processuploadresponse(response);
              50:                                }
              51:                                catch (aggregateexception aggregateexception)
              52:                                {
              53:                                    console.foregroundcolor = consolecolor.red;
              54:                                    console.writeline(string.format(exception : , aggregateexception));
              55:                                }
              56:                            });
              57:              }
              58:          }
              59:      }
              60:      catch (exception ex)
              61:      {
              62:          console.foregroundcolor = consolecolor.red;
              63:          console.writeline(ex.message);
              64:      }
              65:  } 
              66:   
              67:  /// 
              68:  /// process download response object
              69:  /// 
              70:  ///awaitable httpresponsemessage task value
              71:  private static void processuploadresponse(task response)
              72:  {
              73:      if (response.result.issuccessstatuscode)
              74:      {
              75:          string uploadmessage = string.format(
            upload completed @ {0}, {1} time ,
              76:                      datetime.now.tolongdatestring(),
              77:                      datetime.now.tolongtimestring());
              78:          console.foregroundcolor = consolecolor.green;
              79:          console.writeline(string.format({0}
            upload message : 
            {1}, uploadmessage,
              80:              jsonconvert.serializeobject(response.result.content.readasasync>().tryresult(), formatting.indented)));
              81:      }
              82:      else
              83:      {
              84:          processfailresponse(response);
              85:      }
              86:  }

             

            数据流项目由可扩展类和方法组成,本文就不再详述。下篇文章中将介绍“使用https 开发项目”

            下载源代码

            原文链接:https://www.codeproject.com/articles/838274/web-api-thoughts-of-data-streaming#hist

            ASP.NET Web API 应用教程(一) ——数据流使用

             

            相信已经有很多文章来介绍asp.net web api 技术,本系列文章主要介绍如何使用数据流,https,以及可扩展的web api 方面的技术,系列文章主要有三篇内容。

            主要内容如下:

            i 数据流

            ii 使用https

            iii 可扩展的web api 文档

             

            项目环境要求

            • vs 2012(sp4)及以上,
            • .net 框架4.5.1
            • nuget包,可在packages.config 文件中查寻

              本文涉及的知识点

              1. actionfilter
              2. authorizationfilter
              3. delegatehandler
              4. different web api routing 属性
              5. mediatypeformatter
              6. owin
              7. self hosting
              8. web api 文档及可扩展功能

                .net 框架

                1. async/await
                2. .net reflection
                3. serialization
                4. asp.net web api/mvc error handling
                5. iis ,https 及certificate
                6. 设计准则及技术

                  前言

                  ASP.NET Web API 应用教程(一) ——数据流使用

                   

                  自从asp.net mvc 4之后.net 框架开始支持asp.net web api ,asp.net web api 基于http 协议建立的,是构建 restful 服务和处理数据的理想平台,旨在使用http 技术实现对多平台的支持。

                  asp.net web api 以request-response 的消息转换模式为主,客户端向服务器发送请求,服务器端响应客户端请求。响应可同步或异步。

                  个人认为使用web api创建应用需要注意的三个关键点:

                  • 采用服务及方法满足的目标
                  • 每个方法的输入,如请求
                  • 每个方法的输出,如响应

                    通常情况下,asp.net web api 定义method语法与http方法一一对应的,如自定义方法名 getpysicians(),则与http中get 方法匹配。下图是常用匹配表。

                     

                    ASP.NET Web API 应用教程(一) ——数据流使用


                    但是此方法在很多情况下,并不实用,假如你想在单个api controller 类中定义多个get 或post 方法,在这种情况下,需要定义包含action 的路径,将action 作为uri 的一部分。以下是配置代码:

                       1:  public static void register(httpconfiguration config)
                       2:  {
                       3:      // web api configuration and services
                       4:      // web api routes
                       5:       config.maphttpattributeroutes();
                       6:      
                       7:       config.routes.maphttproute(name: physicianapi,
                       8:                  routetemplate: {controller}/{action}/{id},
                       9:                  defaults: new { id = routeparameter.optional });
                      10:  }

                    但是此方法不足以应对所有情况,如果想实现从*仓库删除文件,并且想调用同一个方法来获取文件,这种情况下,web api 框架需要伪装get 及delete对应的http 方法属性。如图所示:

                    ASP.NET Web API 应用教程(一) ——数据流使用

                    removefile 方法可被delete(httpdelete) 或 get(httpget)方法同时调用,从某种程度来说,http 方法使开发人员命名 api“方法”变得简单而标准。

                    web api框架也提供了一些其他功能来处理路径方面的问题,与mvc 的路径处理方法相似。因此可定义不同类型的action方法。

                    数据流

                    网络app 最常见的执行操作就是获取数据流。asp.net web api 能够处理客户端与服务器端传输的重量级的数据流,数据流可来源于目录文件,也可是数据库中的二进制文件。本文主要介绍两种方法“download”和“upload”实现数据流相关的功能,download是从服务器下载数据操作,而upload则是上传数据到服务器。

                    相关项目

                    • webapidatastreaming
                    • webapiclient
                    • pocolibrary

                      在对代码解释之前,首先来了解如何配置iis(7.5)和web api 服务web.config 文件。

                      1. 保证downloads/uploads 涉及的文件具有读写权限。

                      2. 保证有足够容量的内容或因*空间处理大文件。

                      3. 如果文件较大

                      a. 配置web.config 文件时,保证 maxrequestlength 时响应时间 executiontimeout 合理。具体的值主要依赖于数据大小,允许一次性上传的最大数据为2 gb

                      ASP.NET Web API 应用教程(一) ——数据流使用

                      b. 保证 maxallowedcontentlength 在requestfiltering部分配置下正确设置,默认值为30mb,最大值4gb

                      ASP.NET Web API 应用教程(一) ——数据流使用

                      一旦完成预先配置,那么创建数据流服务就非常简单了,首先 需要定义文件流“apicontroller”,如下:

                         1:  /// 
                         2:  /// file streaming api
                         3:  /// 
                         4:  [routeprefix(filestreaming)]
                         5:  [requestmodelvalidator]
                         6:  public class streamfilescontroller : apicontroller
                         7:  {
                         8:      /// 
                         9:      /// get file meta data
                        10:      /// 
                        11:      ///filename value
                        12:      /// filemeta data response.
                        13:      [route(getfilemetadata)]
                        14:      public httpresponsemessage getfilemetadata(string filename)
                        15:      {
                        16:          // .........................................
                        17:          // full code available in the source control
                        18:          // .........................................
                        19:   
                        20:      }
                        21:   
                        22:      /// 
                        23:      /// search file and return its meta data in all download directories
                        24:      /// 
                        25:      ///filename value
                        26:      /// list of file meta datas response
                        27:      [httpget]
                        28:      [route(searchfileindownloaddirectory)]
                        29:      public httpresponsemessage searchfileindownloaddirectory(string filename)
                        30:      {
                        31:          // .........................................
                        32:          // full code available in the source control
                        33:          // .........................................
                        34:      }
                        35:   
                        36:      /// 
                        37:      /// asynchronous download file
                        38:      /// 
                        39:      ///filename value
                        40:      /// tasked file stream response
                        41:      [route(downloadasync)]
                        42:      [httpget]
                        43:      public async task downloadfileasync(string filename)
                        44:      {
                        45:          // .........................................
                        46:          // full code available in the source control
                        47:          // .........................................
                        48:      }
                        49:   
                        50:      /// 
                        51:      /// download file
                        52:      /// 
                        53:      ///filename value
                        54:      /// file stream response
                        55:      [route(download)]
                        56:      [httpget]
                        57:      public httpresponsemessage downloadfile(string filename)
                        58:      {
                        59:          // .........................................
                        60:          // full code available in the source control
                        61:          // .........................................
                        62:      }
                        63:   
                        64:      /// 
                        65:      /// upload file(s)
                        66:      /// 
                        67:      ///an indicator to overwrite a file if it exist in the server
                        68:      /// message response
                        69:      [route(upload)]
                        70:      [httppost]
                        71:      public httpresponsemessage uploadfile(bool overwrite)
                        72:      {
                        73:          // .........................................
                        74:          // full code available in the source control
                        75:          // .........................................
                        76:      }
                        77:   
                        78:      /// 
                        79:      /// asynchronous upload file
                        80:      /// 
                        81:      ///an indicator to overwrite a file if it exist in the server
                        82:      /// tasked message response
                        83:      [route(uploadasync)]
                        84:      [httppost]
                        85:      public async task uploadfileasync(bool overwrite)
                        86:      {
                        87:          // .........................................
                        88:          // full code available in the source control
                        89:          // .........................................
                        90:      }
                        91:  }

                      download 服务方法首先需要确认请求的文件是否存在,如果未找到,则返回错误提示“file is not found”,如果找到此文件,内容则转换为字节附加到响应对象,为“application/octet-stream” mimi 内容类型。

                         1:  /// 
                         2:  /// download file
                         3:  /// 
                         4:  ///filename value
                         5:  /// file stream response
                         6:  [route(download)]
                         7:  [httpget]
                         8:  public httpresponsemessage downloadfile(string filename)
                         9:  {
                        10:      httpresponsemessage response = request.createresponse();
                        11:      filemetadata metadata = new filemetadata();
                        12:      try
                        13:      {
                        14:          string filepath = path.combine(this.getdownloadpath(), @, filename);
                        15:          fileinfo fileinfo = new fileinfo(filepath);
                        16:   
                        17:          if (!fileinfo.exists)
                        18:          {
                        19:              metadata.fileresponsemessage.isexists = false;
                        20:              metadata.fileresponsemessage.content = string.format({0} file is not found !, filename);
                        21:              response = request.createresponse(httpstatuscode.notfound, metadata, new mediatypeheadervalue(text/json));
                        22:          }
                        23:          else
                        24:          {
                        25:              response.headers.acceptranges.add(bytes);
                        26:              response.statuscode = httpstatuscode.ok;
                        27:              response.content = new streamcontent(fileinfo.readstream());
                        28:              response.content.headers.contentdisposition = new contentdispositionheadervalue(attachment);
                        29:              response.content.headers.contentdisposition.filename = filename;
                        30:              response.content.headers.contenttype = new mediatypeheadervalue(application/octet-stream);
                        31:              response.content.headers.contentlength = fileinfo.length;
                        32:          }
                        33:      }
                        34:      catch (exception exception)
                        35:      {
                        36:          // log exception and return gracefully
                        37:          metadata = new filemetadata();
                        38:          metadata.fileresponsemessage.content = processexception(exception);
                        39:          response = request.createresponse(httpstatuscode.internalservererror, metadata, new mediatypeheadervalue(text/json));
                        40:      }
                        41:      return response;
                        42:  }

                      upload服务方法则会在multipart/form-data mimi 内容类型执行,首先会检测http 请求的内容类型是否是多主体,如果是,则对比内容长度是否超过最大尺寸,如果没有超过,则开始上传内容,当操作完成之后,则提示相应的信息。

                      代码片段如下:

                         1:  /// 
                         2:  /// upload file(s)
                         3:  /// 
                         4:  ///an indicator to overwrite a file if it exist in the server.
                         5:  /// message response
                         6:  [route(upload)]
                         7:  [httppost]
                         8:  public httpresponsemessage uploadfile(bool overwrite)
                         9:  {
                        10:      httpresponsemessage response = request.createresponse();
                        11:      list fileresponsemessages = new list();
                        12:      fileresponsemessage fileresponsemessage = new fileresponsemessage { isexists = false };
                        13:   
                        14:      try
                        15:      {
                        16:          if (!request.content.ismimemultipartcontent())
                        17:          {
                        18:              fileresponsemessage.content = upload data request is not valid !;
                        19:              fileresponsemessages.add(fileresponsemessage);
                        20:              response = request.createresponse(httpstatuscode.unsupportedmediatype, fileresponsemessages, new mediatypeheadervalue(text/json));
                        21:          }
                        22:   
                        23:          else
                        24:          {
                        25:              response = processuploadrequest(overwrite);
                        26:          }
                        27:      }
                        28:      catch (exception exception)
                        29:      {
                        30:          // log exception and return gracefully
                        31:          fileresponsemessage = new fileresponsemessage { isexists = false };
                        32:          fileresponsemessage.content = processexception(exception);
                        33:          fileresponsemessages.add(fileresponsemessage);
                        34:          response = request.createresponse(httpstatuscode.internalservererror, fileresponsemessages, new mediatypeheadervalue(text/json));
                        35:   
                        36:      }
                        37:      return response;
                        38:  }
                        39:   
                        40:  /// 
                        41:  /// asynchronous upload file
                        42:  /// 
                        43:  ///an indicator to overwrite a file if it exist in the server.
                        44:  /// tasked message response
                        45:  [route(uploadasync)]
                        46:  [httppost]
                        47:  public async task uploadfileasync(bool overwrite)
                        48:  {
                        49:      return await new taskfactory().startnew(
                        50:         () =>
                        51:         {
                        52:             return uploadfile(overwrite);
                        53:         });
                        54:  }
                        55:   
                        56:  /// 
                        57:  /// process upload request in the server
                        58:  ///  
                        59:  ///an indicator to overwrite a file if it exist in the server.
                        60:  /// list of message object
                        61:  private httpresponsemessage processuploadrequest(bool overwrite)
                        62:  {
                        63:      // .........................................
                        64:      // full code available in the source control
                        65:      // .........................................
                        66:  }

                      调用download 及 upload 文件方法是控制台应用,app 假定文件流服务通过httpclient和相关类。基本下载文件代码,创建下载http 请求对象。

                         1:  /// 
                         2:  /// download file
                         3:  /// 
                         4:  /// awaitable task object
                         5:  private static async task downloadfile()
                         6:  {
                         7:      console.foregroundcolor = consolecolor.green;
                         8:      console.writeline(please specify file name  with extension and press enter :- );
                         9:      string filename = console.readline();
                        10:      string localdownloadpath = string.concat(@c:, filename); // the path can be configurable
                        11:      bool overwrite = true;
                        12:      string actionurl = string.concat(downloadasync?filename=, filename);
                        13:   
                        14:      try
                        15:      {
                        16:          console.writeline(string.format(start downloading @ {0}, {1} time ,
                        17:              datetime.now.tolongdatestring(),
                        18:              datetime.now.tolongtimestring()));
                        19:   
                        20:   
                        21:          using (httpclient httpclient = new httpclient())
                        22:          {
                        23:              httpclient.baseaddress = basestreamingurl;
                        24:              httprequestmessage request = new httprequestmessage(httpmethod.get, actionurl);
                        25:   
                        26:              await httpclient.sendasync(request, httpcompletionoption.responseheadersread).
                        27:                  continuewith((response)
                        28:                      =>
                        29:                  {
                        30:                      console.writeline();
                        31:                      try
                        32:                      {
                        33:                          processdownloadresponse(localdownloadpath, overwrite, response);
                        34:                      }
                        35:                      catch (aggregateexception aggregateexception)
                        36:                      {
                        37:                          console.foregroundcolor = consolecolor.red;
                        38:                          console.writeline(string.format(exception : , aggregateexception));
                        39:                      }
                        40:                  });
                        41:          }
                        42:      }
                        43:      catch (exception ex)
                        44:      {
                        45:          console.foregroundcolor = consolecolor.red;
                        46:          console.writeline(ex.message);
                        47:      }
                        48:  }
                        49:   
                        50:   
                        51:  /// 
                        52:  /// process download response object
                        53:  /// 
                        54:  ///local download file path
                        55:  ///an indicator to overwrite a file if it exist in the client.
                        56:  ///awaitable httpresponsemessage task value
                        57:  private static void processdownloadresponse(string localdownloadfilepath, bool overwrite,
                        58:      task response)
                        59:  {
                        60:      if (response.result.issuccessstatuscode)
                        61:      {
                        62:          response.result.content.downloadfile(localdownloadfilepath, overwrite).
                        63:              continuewith((downloadmessage)
                        64:                  =>
                        65:              {
                        66:                  console.foregroundcolor = consolecolor.green;
                        67:                  console.writeline(downloadmessage.tryresult());
                        68:              });
                        69:      }
                        70:      else
                        71:      {
                        72:          processfailresponse(response);
                        73:      }
                        74:  }

                       

                      注意上述代码中httpclient 对象发送请求,并等待响应发送header内容(httpcompletionoption.responseheadersread )。而不是发送全部的响应内容文件。一旦response header 被读,则执行验证,一旦验证成功,则执行下载方法。

                      以下代码调用upload 文件流,与下载方法类似,创建多主体表单数据,并发送给服务器端。

                         1:  /// 
                         2:  /// upload file
                         3:  /// 
                         4:  /// awaitable task object
                         5:  private static async task uploadfile()
                         6:  {
                         7:      try
                         8:      {
                         9:          string uploadrequesturi = uploadasync?overwrite=true;
                        10:   
                        11:          multipartformdatacontent formdatacontent = new multipartformdatacontent();
                        12:   
                        13:          // validate the file and add to multipartformdatacontent object
                        14:          formdatacontent.adduploadfile(@c:
                      ophoto.png);
                        15:          formdatacontent.adduploadfile(@c:readme.txt);
                        16:   
                        17:          if (!formdatacontent.hascontent()) // no files found to be uploaded
                        18:          {
                        19:              console.foregroundcolor = consolecolor.red;
                        20:              console.write(formdatacontent.getuploadfileerrormesage());
                        21:              return;
                        22:          }
                        23:          else
                        24:          {
                        25:              string uploaderrormessage = formdatacontent.getuploadfileerrormesage();
                        26:              if (!string.isnullorwhitespace(uploaderrormessage)) // some files couldn't be found
                        27:              {
                        28:                  console.foregroundcolor = consolecolor.red;
                        29:                  console.write(uploaderrormessage);
                        30:              }
                        31:   
                        32:              httprequestmessage request = new httprequestmessage(httpmethod.post, uploadrequesturi);
                        33:              request.content = formdatacontent;
                        34:   
                        35:              using (httpclient httpclient = new httpclient())
                        36:              {
                        37:                  console.foregroundcolor = consolecolor.green;
                        38:                  console.writeline(string.format(start uploading @ {0}, {1} time ,
                        39:                  datetime.now.tolongdatestring(),
                        40:                  datetime.now.tolongtimestring()));
                        41:   
                        42:                  httpclient.baseaddress = basestreamingurl;
                        43:                  await httpclient.sendasync(request).
                        44:                        continuewith((response)
                        45:                            =>
                        46:                            {
                        47:                                try
                        48:                                {
                        49:                                    processuploadresponse(response);
                        50:                                }
                        51:                                catch (aggregateexception aggregateexception)
                        52:                                {
                        53:                                    console.foregroundcolor = consolecolor.red;
                        54:                                    console.writeline(string.format(exception : , aggregateexception));
                        55:                                }
                        56:                            });
                        57:              }
                        58:          }
                        59:      }
                        60:      catch (exception ex)
                        61:      {
                        62:          console.foregroundcolor = consolecolor.red;
                        63:          console.writeline(ex.message);
                        64:      }
                        65:  } 
                        66:   
                        67:  /// 
                        68:  /// process download response object
                        69:  /// 
                        70:  ///awaitable httpresponsemessage task value
                        71:  private static void processuploadresponse(task response)
                        72:  {
                        73:      if (response.result.issuccessstatuscode)
                        74:      {
                        75:          string uploadmessage = string.format(
                      upload completed @ {0}, {1} time ,
                        76:                      datetime.now.tolongdatestring(),
                        77:                      datetime.now.tolongtimestring());
                        78:          console.foregroundcolor = consolecolor.green;
                        79:          console.writeline(string.format({0}
                      upload message : 
                      {1}, uploadmessage,
                        80:              jsonconvert.serializeobject(response.result.content.readasasync>().tryresult(), formatting.indented)));
                        81:      }
                        82:      else
                        83:      {
                        84:          processfailresponse(response);
                        85:      }
                        86:  }

                       

                      数据流项目由可扩展类和方法组成,本文就不再详述。下篇文章中将介绍“使用https 开发项目”