I encountered the problem of encapsulating the Media type multipart/form-data when writing a generic HTTP component. This article briefly introduces the definition, application and elementary implementation of the media type multipart/form-data in the HTTP protocol.

Definition of multipart/form-information

The media type multipart/form-information follows the multipart MIME data stream definition (which can be constitute in Department 5.1 - RFC2046), which roughly means that the data trunk of the media type multipart/course-data consists of multiple parts separated by a fixed Boundary.

multipart/form-data request body layout

The layout of the multipart/form-information request body is as follows.

                                                                              1                                                                                2                                                                                iii                                                                                four                                                                                5                                                                                6                                                                                7                                                                                8                                                                                9                                                    10                                                    xi                                                    12                                                    13                                                    14                                                    xv                                                    xvi                                                    17                                                    xviii                                                    19                                                    20                                                                        
                                                                              # 请求头 - 这个是必须的,需要指定Content-Type为multipart/course-data,指定唯一边界值                                                                                                            Content-Blazon: multipart/grade-information; boundary=${Boundary}                                                                                                                                                                                                                        # 请求体                                                                                                            --${Boundary}                                                                                                            Content-Disposition: grade-data; name="name of file"                                                                                                            Content-Blazon: awarding/octet-stream                                                                                                                                                                                                                        bytes of file                                                                                                            --${Boundary}                                                                                                            Content-Disposition: form-data; name="name of pdf"; filename="pdf-file.pdf"                                                                                                            Content-Type: application/octet-stream                                                                                                                                                                                                                        bytes of pdf file                                                                                                            --${Purlieus}                                                                                                            Content-Disposition: form-data; name="fundamental"                                                                                                            Content-Blazon: text/manifestly;charset=UTF-8                                                                                                                                                                                                                        text encoded in UTF-8                                                                                                            --${Purlieus}--                                                                                                    

The virtually obvious differences between the media blazon multipart/course-data versus other media types such as application/ten-world wide web-course-urlencoded are

  • The Content-Type attribute of the request header, in addition to specifying multipart/form-data, also requires the definition of the boundary parameter
  • The request line data in the request torso is composed of multiple parts, and the value pattern of the boundary parameter - ${Boundary} is used to separate each private division
  • The request header Content-Disposition: course-information; name="${PART_NAME}"; must exist present in each section, where ${PART_NAME} needs to exist URL encoded, and the filename field tin be used to indicate the proper name of the file, but it is less binding than the name attribute (equally there is no confirmation that the local file is available or objectionable)
  • Each part tin define Content-Blazon and the data body of that part separately
  • The request body ends with the value pattern -${Boundary}-- of the boundary parameter

RFC7578 mentions two multipart/course-data expired use, one is the use of Content-Transfer-Encoding request header, here also do not expand its utilise, the second is the request trunk of a unmarried form attribute manual of multiple binary file way recommended to switch to multipart/mixed (a "name" corresponds to multiple binary file scenario)

Special.

  • If the content of a function is text, its Content-Blazon is text/plain, you can specify the corresponding character set, such as Content-Type: text/plain;charset=UTF-viii
  • The default charset tin be specified via the charset aspect, which is used as follows.
                                                  one                                                    2                                                    3                                                    4                                                    5                                                    half-dozen                                                    7                                                    eight                                                                        
                                                                              Content-Disposition: form-information; name="_charset_"                                                                                                                                                                                                                        UTF-8                                                                                                            --ABCDE--                                                                                                            Content-Disposition: form-data; name="field"                                                                                                                                                                                                                        ...text encoded in UTF-viii...                                                                                                            ABCDE--                                                                                                    

Boundary parameter value statute

The Boundary parameter takes the following value statute.

  • The value of the Purlieus must brainstorm with a double horizontal bar – in the middle of the English, this – is called the leading hyphen
  • The value of the Boundary must not contain more than seventy characters in addition to the leading hyphen.
  • The value of the Boundary must not contain characters that are disabled by the HTTP protocol or the URL, such every bit the colon: etc.
  • Each – ${Boundary} before the default mandatory must exist CRLF, if a part of the text type request body ends with CRLF, and so in the request body of the secondary system format, at that place must exist two CRLF explicitly, if a part of the request torso does not terminate with CRLF, can merely exist a CRLF, these ii cases are called the separator of the explicit type and implicit type, said more abstract, meet the following example.
                                                                              1                                                                                ii                                                                                3                                                                                4                                                                                5                                                                                6                                                                                vii                                                                                eight                                                                                nine                                                    10                                                    11                                                    12                                                    xiii                                                    14                                                    15                                                    16                                                    17                                                    18                                                    19                                                    20                                                    21                                                                        
                                                                              # 请求头                                                                                                            Content-blazon: multipart/data; boundary="--abcdefg"                                                                                                                                                                                                                        --abcdefg                                                                                                            Content-Disposition: form-data; proper noun="x"                                                                                                            Content-type: text/patently; charset=ascii                                                                                                                                                                                                                        It does NOT end with a linebreak # <=== 这里没有CRLF,隐式类型                                                                                                            --abcdefg                                                                                                            Content-Disposition: form-data; name="y"                                                                                                            Content-type: text/plain; charset=ascii                                                                                                                                                                                                                        It DOES end with a linebreak # <=== 这里有CRLF,显式类型                                                                                                                                                                                                                        --abcdefg                                                                                                                                                                                                                        ## 直观看隐式类型的CRLF                                                                                                            It does Not end with a linebreak CRLF --abcdefg                                                                                                                                                                                                                        ## 直观看显式类型的CRLF                                                                                                            It DOES terminate with a linebreak CRLF CRLF --abcdefg                                                                                                    

Implementing POST requests for multipart/form-information media types

Here just for the depression JDK version of HttpURLConnection and high JDK version of the built-in HttpClient to write multipart/grade-data media type of POST requests HTTP client, others such equally custom Socket implementation can be completed forth similar lines. Commencement introduce org.springframework.boot:spring-boot-starter-web:2.six.0 to do a simple controller method.

                                                  1                                                    ii                                                    3                                                    4                                                    5                                                    6                                                    seven                                                    eight                                                                        
                                                                                                            @RestController                                                                                                                                          public                              class                              TestController                              {                                                                                                                                                                                                                                                      @PostMapping                              (                              path                              =                              "/test"                              )                                                                                                                                          public                              ResponseEntity                              <?>                              exam                              (                              MultipartHttpServletRequest                              request                              )                              {                                                                                                                                          return                              ResponseEntity                              .                              ok                              (                              "ok"                              );                                                                                                                                          }                                                                                                                                          }                                                                                                    

Postman's simulated request is as follows.

image

The request parameters obtained by the backend controller are as follows.

image

The client written later can call this interface directly for debugging.

Module that encapsulates the conversion of asking bodies into byte containers

Here the boundary values are all implemented explicitly, and the boundary values are generated directly with a stock-still prefix plus the UUID. Some simplifications are made in the simple implementation.

  • Only text form data and binary (file) form data are considered for submission
  • Based on the previous bespeak, each department explicitly specifies Content-Type as the request header
  • Text encoding is fixed to UTF-8

Write a MultipartWriter.

                                                                              1                                                                                two                                                                                iii                                                                                4                                                                                five                                                                                half dozen                                                                                7                                                                                viii                                                                                9                                                                                10                                                                                11                                                                                12                                                                                xiii                                                                                14                                                                                fifteen                                                                                16                                                                                17                                                                                eighteen                                                                                nineteen                                                                                20                                                                                21                                                                                22                                                                                23                                                                                24                                                                                25                                                                                26                                                                                27                                                                                28                                                                                29                                                                                xxx                                                                                31                                                                                32                                                                                33                                                                                34                                                                                35                                                                                36                                                                                37                                                                                38                                                                                39                                                                                xl                                                                                41                                                                                42                                                                                43                                                                                44                                                                                45                                                                                46                                                                                47                                                                                48                                                                                49                                                                                l                                                                                51                                                                                52                                                                                53                                                                                54                                                                                55                                                                                56                                                                                57                                                                                58                                                                                59                                                                                sixty                                                                                61                                                                                62                                                                                63                                                                                64                                                                                65                                                                                66                                                                                67                                                                                68                                                                                69                                                                                lxx                                                                                71                                                                                72                                                                                73                                                                                74                                                                                75                                                                                76                                                                                77                                                                                78                                                                                79                                                                                fourscore                                                                                81                                                                                82                                                                                83                                                                                84                                                                                85                                                                                86                                                                                87                                                                                88                                                                                89                                                                                90                                                                                91                                                                                92                                                                                93                                                                                94                                                                                95                                                                                96                                                                                97                                                                                98                                                                                99                                                    100                                                    101                                                    102                                                    103                                                    104                                                    105                                                    106                                                    107                                                    108                                                    109                                                    110                                                    111                                                    112                                                    113                                                    114                                                    115                                                    116                                                    117                                                    118                                                    119                                                    120                                                    121                                                    122                                                    123                                                    124                                                    125                                                    126                                                    127                                                    128                                                    129                                                    130                                                    131                                                    132                                                    133                                                    134                                                    135                                                    136                                                    137                                                    138                                                    139                                                    140                                                    141                                                    142                                                    143                                                    144                                                    145                                                    146                                                    147                                                    148                                                    149                                                    150                                                    151                                                    152                                                    153                                                    154                                                    155                                                    156                                                    157                                                    158                                                    159                                                    160                                                    161                                                    162                                                    163                                                    164                                                    165                                                    166                                                    167                                                    168                                                    169                                                    170                                                    171                                                    172                                                    173                                                    174                                                    175                                                    176                                                    177                                                    178                                                    179                                                    180                                                    181                                                    182                                                    183                                                    184                                                    185                                                    186                                                    187                                                    188                                                    189                                                    190                                                    191                                                    192                                                    193                                                                        
                                                                                                            public                              course                              MultipartWriter                              {                                                                                                                                                                                                                                                      private                              static                              final                              Charset                              DEFAULT_CHARSET                              =                              StandardCharsets                              .                              UTF_8                              ;                                                                                                                                          private                              static                              final                              byte                              []                              FIELD_SEP                              =                              ": "                              .                              getBytes                              (                              StandardCharsets                              .                              ISO_8859_1                              );                                                                                                                                          private                              static                              final                              byte                              []                              CR_LF                              =                              "\r\north"                              .                              getBytes                              (                              StandardCharsets                              .                              ISO_8859_1                              );                                                                                                                                          private                              static                              final                              String                              TWO_HYPHENS_TEXT                              =                              "--"                              ;                                                                                                                                          individual                              static                              final                              byte                              []                              TWO_HYPHENS                              =                              TWO_HYPHENS_TEXT                              .                              getBytes                              (                              StandardCharsets                              .                              ISO_8859_1                              );                                                                                                                                          private                              static                              concluding                              Cord                              CONTENT_DISPOSITION_KEY                              =                              "Content-Disposition"                              ;                                                                                                                                          private                              static                              final                              String                              CONTENT_TYPE_KEY                              =                              "Content-Type"                              ;                                                                                                                                          private                              static                              final                              String                              DEFAULT_CONTENT_TYPE                              =                              "multipart/form-information; boundary="                              ;                                                                                                                                          individual                              static                              final                              String                              DEFAULT_BINARY_CONTENT_TYPE                              =                              "application/octet-stream"                              ;                                                                                                                                          individual                              static                              final                              String                              DEFAULT_TEXT_CONTENT_TYPE                              =                              "text/plain;charset=UTF-viii"                              ;                                                                                                                                          private                              static                              concluding                              String                              DEFAULT_CONTENT_DISPOSITION_VALUE                              =                              "form-data; name=\"%s\""                              ;                                                                                                                                          private                              static                              final                              String                              FILE_CONTENT_DISPOSITION_VALUE                              =                              "form-information; name=\"%south\"; filename=\"%due south\""                              ;                                                                                                                                                                                                                                                      private                              final                              Map                              <                              String                              ,                              Cord                              >                              headers                              =                              new                              HashMap                              <>(                              eight                              );                                                                                                                                          private                              final                              List                              <                              AbstractMultipartPart                              >                              parts                              =                              new                              ArrayList                              <>();                                                                                                                                          private                              final                              String                              boundary                              ;                                                                                                                                                                                                                                                      private                              MultipartWriter                              (                              Cord                              purlieus                              )                              {                                                                                                                                          this                              .                              boundary                              =                              Objects                              .                              isNull                              (                              purlieus                              )                              ?                              TWO_HYPHENS_TEXT                              +                                                                                                                                          UUID                              .                              randomUUID                              ().                              toString                              ().                              supervene upon                              (                              "-"                              ,                              ""                              )                              :                              purlieus                              ;                                                                                                                                          this                              .                              headers                              .                              put                              (                              CONTENT_TYPE_KEY                              ,                              DEFAULT_CONTENT_TYPE                              +                              this                              .                              boundary                              );                                                                                                                                          }                                                                                                                                                                                                                                                      public                              static                              MultipartWriter                              newMultipartWriter                              (                              String                              boundary                              )                              {                                                                                                                                          render                              new                              MultipartWriter                              (                              purlieus                              );                                                                                                                                          }                                                                                                                                                                                                                                                      public                              static                              MultipartWriter                              newMultipartWriter                              ()                              {                                                                                                                                          render                              new                              MultipartWriter                              (                              null                              );                                                                                                                                          }                                                                                                                                                                                                                                                      public                              MultipartWriter                              addHeader                              (                              String                              key                              ,                              String                              value                              )                              {                                                                                                                                          if                              (!                              CONTENT_TYPE_KEY                              .                              equalsIgnoreCase                              (                              key                              ))                              {                                                                                                                                          headers                              .                              put                              (                              key                              ,                              value                              );                                                                                                                                          }                                                                                                                                          return                              this                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      public                              MultipartWriter                              addTextPart                              (                              String                              name                              ,                              String                              text                              )                              {                                                                                                                                          parts                              .                              add                              (                              new                              TextPart                              (                              String                              .                              format                              (                              DEFAULT_CONTENT_DISPOSITION_VALUE                              ,                              name                              ),                              DEFAULT_TEXT_CONTENT_TYPE                              ,                              this                              .                              boundary                              ,                              text                              ));                                                                                                                                          return                              this                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      public                              MultipartWriter                              addBinaryPart                              (                              String                              name                              ,                              byte                              []                              bytes                              )                              {                                                                                                                                          parts                              .                              add                              (                              new                              BinaryPart                              (                              String                              .                              format                              (                              DEFAULT_CONTENT_DISPOSITION_VALUE                              ,                              name                              ),                              DEFAULT_BINARY_CONTENT_TYPE                              ,                              this                              .                              boundary                              ,                              bytes                              ));                                                                                                                                          return                              this                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      public                              MultipartWriter                              addFilePart                              (                              String                              proper name                              ,                              File                              file                              )                              {                                                                                                                                          parts                              .                              add                              (                              new                              FilePart                              (                              String                              .                              format                              (                              FILE_CONTENT_DISPOSITION_VALUE                              ,                              proper noun                              ,                              file                              .                              getName                              ()),                              DEFAULT_BINARY_CONTENT_TYPE                              ,                              this                              .                              boundary                              ,                              file                              ));                                                                                                                                          return                              this                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      private                              static                              void                              writeHeader                              (                              Cord                              key                              ,                              String                              value                              ,                              OutputStream                              out                              )                              throws                              IOException                              {                                                                                                                                          writeBytes                              (                              key                              ,                              out                              );                                                                                                                                          writeBytes                              (                              FIELD_SEP                              ,                              out                              );                                                                                                                                          writeBytes                              (                              value                              ,                              out                              );                                                                                                                                          writeBytes                              (                              CR_LF                              ,                              out                              );                                                                                                                                          }                                                                                                                                                                                                                                                      private                              static                              void                              writeBytes                              (                              Cord                              text                              ,                              OutputStream                              out                              )                              throws                              IOException                              {                                                                                                                                          out                              .                              write                              (                              text                              .                              getBytes                              (                              DEFAULT_CHARSET                              ));                                                                                                                                          }                                                                                                                                                                                                                                                      individual                              static                              void                              writeBytes                              (                              byte                              []                              bytes                              ,                              OutputStream                              out                              )                              throws                              IOException                              {                                                                                                                                          out                              .                              write                              (                              bytes                              );                                                                                                                                          }                                                                                                                                                                                                                                                      interface                              MultipartPart                              {                                                                                                                                                                                                                                                      void                              writeBody                              (                              OutputStream                              os                              )                              throws                              IOException                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      @RequiredArgsConstructor                                                                                                                                          public                              static                              abstract                              class                              AbstractMultipartPart                              implements                              MultipartPart                              {                                                                                                                                                                                                                                                      protected                              final                              String                              contentDispositionValue                              ;                                                                                                                                          protected                              terminal                              String                              contentTypeValue                              ;                                                                                                                                          protected                              concluding                              Cord                              boundary                              ;                                                                                                                                                                                                                                                      protected                              String                              getContentDispositionValue                              ()                              {                                                                                                                                          return                              contentDispositionValue                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      protected                              String                              getContentTypeValue                              ()                              {                                                                                                                                          return                              contentTypeValue                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      protected                              Cord                              getBoundary                              ()                              {                                                                                                                                          return                              boundary                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      public                              concluding                              void                              write                              (                              OutputStream                              out                              )                              throws                              IOException                              {                                                                                                                                          writeBytes                              (                              TWO_HYPHENS                              ,                              out                              );                                                                                                                                          writeBytes                              (                              getBoundary                              (),                              out                              );                                                                                                                                          writeBytes                              (                              CR_LF                              ,                              out                              );                                                                                                                                          writeHeader                              (                              CONTENT_DISPOSITION_KEY                              ,                              getContentDispositionValue                              (),                              out                              );                                                                                                                                          writeHeader                              (                              CONTENT_TYPE_KEY                              ,                              getContentTypeValue                              (),                              out                              );                                                                                                                                          writeBytes                              (                              CR_LF                              ,                              out                              );                                                                                                                                          writeBody                              (                              out                              );                                                                                                                                          writeBytes                              (                              CR_LF                              ,                              out                              );                                                                                                                                          }                                                                                                                                          }                                                                                                                                                                                                                                                      public                              static                              grade                              TextPart                              extends                              AbstractMultipartPart                              {                                                                                                                                                                                                                                                      private                              final                              String                              text                              ;                                                                                                                                                                                                                                                      public                              TextPart                              (                              String                              contentDispositionValue                              ,                                                                                                                                          String                              contentTypeValue                              ,                                                                                                                                          String                              boundary                              ,                                                                                                                                          Cord                              text                              )                              {                                                                                                                                          super                              (                              contentDispositionValue                              ,                              contentTypeValue                              ,                              boundary                              );                                                                                                                                          this                              .                              text                              =                              text                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      @Override                                                                                                                                          public                              void                              writeBody                              (                              OutputStream                              os                              )                              throws                              IOException                              {                                                                                                                                          os                              .                              write                              (                              text                              .                              getBytes                              (                              DEFAULT_CHARSET                              ));                                                                                                                                          }                                                                                                                                                                                                                                                      @Override                                                                                                                                          protected                              String                              getContentDispositionValue                              ()                              {                                                                                                                                          render                              contentDispositionValue                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      @Override                                                                                                                                          protected                              String                              getContentTypeValue                              ()                              {                                                                                                                                          render                              contentTypeValue                              ;                                                                                                                                          }                                                                                                                                          }                                                                                                                                                                                                                                                      public                              static                              course                              BinaryPart                              extends                              AbstractMultipartPart                              {                                                                                                                                                                                                                                                      private                              final                              byte                              []                              content                              ;                                                                                                                                                                                                                                                      public                              BinaryPart                              (                              String                              contentDispositionValue                              ,                                                                                                                                          String                              contentTypeValue                              ,                                                                                                                                          String                              purlieus                              ,                                                                                                                                          byte                              []                              content                              )                              {                                                                                                                                          super                              (                              contentDispositionValue                              ,                              contentTypeValue                              ,                              boundary                              );                                                                                                                                          this                              .                              content                              =                              content                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      @Override                                                                                                                                          public                              void                              writeBody                              (                              OutputStream                              out                              )                              throws                              IOException                              {                                                                                                                                          out                              .                              write                              (                              content                              );                                                                                                                                          }                                                                                                                                          }                                                                                                                                                                                                                                                      public                              static                              course                              FilePart                              extends                              AbstractMultipartPart                              {                                                                                                                                                                                                                                                      private                              concluding                              File                              file                              ;                                                                                                                                                                                                                                                      public                              FilePart                              (                              String                              contentDispositionValue                              ,                                                                                                                                          String                              contentTypeValue                              ,                                                                                                                                          String                              boundary                              ,                                                                                                                                          File                              file                              )                              {                                                                                                                                          super                              (                              contentDispositionValue                              ,                              contentTypeValue                              ,                              boundary                              );                                                                                                                                          this                              .                              file                              =                              file                              ;                                                                                                                                          }                                                                                                                                                                                                                                                      @Override                                                                                                                                          public                              void                              writeBody                              (                              OutputStream                              out                              )                              throws                              IOException                              {                                                                                                                                          try                              (                              InputStream                              in                              =                              new                              FileInputStream                              (                              file                              ))                              {                                                                                                                                          final                              byte                              []                              buffer                              =                              new                              byte                              [                              4096                              ];                                                                                                                                          int                              l                              ;                                                                                                                                          while                              ((                              l                              =                              in                              .                              read                              (                              buffer                              ))                              !=                              -                              ane                              )                              {                                                                                                                                          out                              .                              write                              (                              buffer                              ,                              0                              ,                              fifty                              );                                                                                                                                          }                                                                                                                                          out                              .                              flush                              ();                                                                                                                                          }                                                                                                                                          }                                                                                                                                          }                                                                                                                                                                                                                                                      public                              void                              forEachHeader                              (                              BiConsumer                              <                              String                              ,                              String                              >                              consumer                              )                              {                                                                                                                                          headers                              .                              forEach                              (                              consumer                              );                                                                                                                                          }                                                                                                                                                                                                                                                      public                              void                              write                              (                              OutputStream                              out                              )                              throws                              IOException                              {                                                                                                                                          if                              (!                              parts                              .                              isEmpty                              ())                              {                                                                                                                                          for                              (                              AbstractMultipartPart                              part                              :                              parts                              )                              {                                                                                                                                          part                              .                              write                              (                              out                              );                                                                                                                                          }                                                                                                                                          }                                                                                                                                          writeBytes                              (                              TWO_HYPHENS                              ,                              out                              );                                                                                                                                          writeBytes                              (                              this                              .                              boundary                              ,                              out                              );                                                                                                                                          writeBytes                              (                              TWO_HYPHENS                              ,                              out                              );                                                                                                                                          writeBytes                              (                              CR_LF                              ,                              out                              );                                                                                                                                          }                                                                                                                                          }                                                                                                    

This form has encapsulated three different types of fractional request body implementations. The forEachHeader() method is used to iterate through the request headers, and the final write() method is used to write the request trunk to the OutputStream.

HttpURLConnection implementation

The implementation lawmaking is as follows (minimal implementation but, without consideration of error tolerance and exception handling).

                                                                              ane                                                                                2                                                                                iii                                                                                iv                                                                                5                                                                                6                                                                                7                                                                                eight                                                                                9                                                    10                                                    11                                                    12                                                    13                                                    14                                                    15                                                    16                                                    17                                                    eighteen                                                    19                                                    20                                                    21                                                    22                                                    23                                                    24                                                    25                                                    26                                                    27                                                    28                                                    29                                                    30                                                    31                                                    32                                                    33                                                    34                                                    35                                                    36                                                                        
                                                                                                            public                              class                              HttpURLConnectionApp                              {                                                                                                                                                                                                                                                      private                              static                              last                              String                              URL                              =                              "http://localhost:9099/examination"                              ;                                                                                                                                                                                                                                                      public                              static                              void                              main                              (                              String                              []                              args                              )                              throws                              Exception                              {                                                                                                                                          MultipartWriter                              author                              =                              MultipartWriter                              .                              newMultipartWriter                              ();                                                                                                                                          author                              .                              addTextPart                              (                              "proper name"                              ,                              "throwable"                              )                                                                                                                                          .                              addTextPart                              (                              "domain"                              ,                              "vlts.cn"                              )                                                                                                                                          .                              addFilePart                              (                              "ico"                              ,                              new                              File                              (                              "I:\\doge_favicon.ico"                              ));                                                                                                                                          DataOutputStream                              requestPrinter                              =                              new                              DataOutputStream                              (                              System                              .                              out                              );                                                                                                                                          writer                              .                              write                              (                              requestPrinter                              );                                                                                                                                          HttpURLConnection                              connection                              =                              (                              HttpURLConnection                              )                              new                              java                              .                              net                              .                              URL                              (                              URL                              ).                              openConnection                              ();                                                                                                                                          connectedness                              .                              setRequestMethod                              (                              "POST"                              );                                                                                                                                          connexion                              .                              addRequestProperty                              (                              "Connection"                              ,                              "Go on-Alive"                              );                                                                                                                                          // 设置请求头                                                                                                                                                                                                      writer                              .                              forEachHeader                              (                              connexion                              ::                              addRequestProperty                              );                                                                                                                                          connection                              .                              setDoInput                              (                              true                              );                                                                                                                                          connection                              .                              setDoOutput                              (                              true                              );                                                                                                                                          connection                              .                              setConnectTimeout                              (                              10000                              );                                                                                                                                          connectedness                              .                              setReadTimeout                              (                              10000                              );                                                                                                                                          DataOutputStream                              out                              =                              new                              DataOutputStream                              (                              connection                              .                              getOutputStream                              ());                                                                                                                                          // 设置请求体                                                                                                                                                                                                      writer                              .                              write                              (                              out                              );                                                                                                                                          StringBuilder                              builder                              =                              new                              StringBuilder                              ();                                                                                                                                          BufferedReader                              reader                              =                              new                              BufferedReader                              (                              new                              InputStreamReader                              (                              connectedness                              .                              getInputStream                              (),                              StandardCharsets                              .                              UTF_8                              ));                                                                                                                                          String                              line                              ;                                                                                                                                          while                              (                              Objects                              .                              nonNull                              (                              line                              =                              reader                              .                              readLine                              ()))                              {                                                                                                                                          builder                              .                              append                              (                              line                              );                                                                                                                                          }                                                                                                                                          int                              responseCode                              =                              connection                              .                              getResponseCode                              ();                                                                                                                                          reader                              .                              close                              ();                                                                                                                                          out                              .                              shut                              ();                                                                                                                                          connexion                              .                              disconnect                              ();                                                                                                                                          System                              .                              out                              .                              printf                              (                              "响应码:%d,响应内容:%s\n"                              ,                              responseCode                              ,                              builder                              );                                                                                                                                          }                                                                                                                                          }                                                                                                    

Implementation response results.

You tin can effort calculation two lines of code to impress the asking body.

                                                  1                                                    2                                                    iii                                                    4                                                    five                                                    half-dozen                                                                        
                                                                                                            MultipartWriter                              writer                              =                              MultipartWriter                              .                              newMultipartWriter                              ();                                                                                                                                          writer                              .                              addTextPart                              (                              "name"                              ,                              "throwable"                              )                                                                                                                                          .                              addTextPart                              (                              "domain"                              ,                              "vlts.cn"                              )                                                                                                                                          .                              addFilePart                              (                              "ico"                              ,                              new                              File                              (                              "I:\\doge_favicon.ico"                              ));                                                                                                                                          DataOutputStream                              requestPrinter                              =                              new                              DataOutputStream                              (                              System                              .                              out                              );                                                                                                                                          writer                              .                              write                              (                              requestPrinter                              );                                                                                                    

Console output as follows.

image

JDK congenital-in HttpClient implementation

JDK11+ built-in HTTP client implementation, the specific archway is java.net.http.HttpClient, the implementation code is as follows.

                                                                              1                                                                                2                                                                                three                                                                                four                                                                                five                                                                                6                                                                                seven                                                                                8                                                                                9                                                    ten                                                    xi                                                    12                                                    13                                                    14                                                    xv                                                    xvi                                                    17                                                    18                                                    xix                                                    20                                                    21                                                    22                                                    23                                                                        
                                                                                                            public                              class                              HttpClientApp                              {                                                                                                                                                                                                                                                      private                              static                              final                              Cord                              URL                              =                              "http://localhost:9099/exam"                              ;                                                                                                                                                                                                                                                      public                              static                              void                              main                              (                              String                              []                              args                              )                              throws                              Exception                              {                                                                                                                                          HttpClient                              httpClient                              =                              HttpClient                              .                              newBuilder                              ()                                                                                                                                          .                              connectTimeout                              (                              Duration                              .                              of                              (                              10                              ,                              ChronoUnit                              .                              SECONDS                              ))                                                                                                                                          .                              build                              ();                                                                                                                                          MultipartWriter                              writer                              =                              MultipartWriter                              .                              newMultipartWriter                              ();                                                                                                                                          writer                              .                              addTextPart                              (                              "proper noun"                              ,                              "throwable"                              )                                                                                                                                          .                              addTextPart                              (                              "domain"                              ,                              "vlts.cn"                              )                                                                                                                                          .                              addFilePart                              (                              "ico"                              ,                              new                              File                              (                              "I:\\doge_favicon.ico"                              ));                                                                                                                                          ByteArrayOutputStream                              out                              =                              new                              ByteArrayOutputStream                              ();                                                                                                                                          author                              .                              write                              (                              out                              );                                                                                                                                          HttpRequest                              .                              Architect                              requestBuilder                              =                              HttpRequest                              .                              newBuilder                              ();                                                                                                                                          writer                              .                              forEachHeader                              (                              requestBuilder                              ::                              header                              );                                                                                                                                          HttpRequest                              request                              =                              requestBuilder                              .                              uri                              (                              URI                              .                              create                              (                              URL                              ))                                                                                                                                          .                              method                              (                              "Post"                              ,                              HttpRequest                              .                              BodyPublishers                              .                              ofByteArray                              (                              out                              .                              toByteArray                              ()))                                                                                                                                          .                              build                              ();                                                                                                                                          HttpResponse                              <                              String                              >                              response                              =                              httpClient                              .                              send                              (                              request                              ,                              HttpResponse                              .                              BodyHandlers                              .                              ofString                              ());                                                                                                                                          Organization                              .                              out                              .                              printf                              (                              "响应码:%d,响应内容:%s\north"                              ,                              response                              .                              statusCode                              (),                              response                              .                              body                              ());                                                                                                                                          }                                                                                                                                          }                                                                                                    

The congenital-in HTTP components are almost all using Reactive programming model, using a relatively depression-level API, which is more than flexible merely not every bit easy to use.

Summary

The media blazon multipart/class-data is commonly used in HTTP requests nether the POST method, and is relatively uncommon as an HTTP response.