2

I'm going to upload files with C++, to a Java spring boot web server.

I constructed the protocol looks like below (in plain text):

POST /gallery/multimedia/uploadvideo HTTP/1.1
Host: 192.168.0.133:8981
Content-Type: multipart/form-data; boundary=------boundary1804289383
Connection: keep-alive

--------boundary1804289383
Content-Type: video/mp4
Content-Disposition: form-data; name="file"; filename="1.mp4"
Content-Length: 948611
Content-Transfer-Encoding: 8bit

... binary video data here ...

--------boundary1804289383--

The server side is Java spring boot server, interface defined as below:

@PostMapping("uploadvideo")
public ResultVo uploadVideo(@RequestParam("file") MultipartFile file);

While posting file, the server responses with code 400, and complains that

Required request part 'file' is not present

However with a simple HTML page, file uploaded successfully, the HTML page listed below:

<html>
    <head></head>
    <body>
        <form id="form" enctype="multipart/form-data" method="post" 
            action="http://192.168.0.133:8981/gallery/multimedia/uploadvideo">
            <input id="file" name="file" type="file" />
            <input id="submit" value="submit" type="submit" />
        </form>
    </body>
</html>

What do I miss?


Edit:

I've tried Postman/Chrome console/curl, all these tools only print the request looks like:

# this is from curl
POST /gallery/multimedia/uploadvideo HTTP/1.1
User-Agent: curl/7.29.0
Host: 192.168.0.133:8981
Accept: */*
Content-Length: 187
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------3c653d03b97f

How should I construct the file part? Any ideas?

Ted Yu
  • 1,784
  • 1
  • 10
  • 16
  • 3
    [Postman](https://www.postman.com) and [Wireshark](https://www.wireshark.org) are your best friends for such problems. – Thomas Sablik Dec 07 '20 at 10:45
  • 1
    Check this answer on how to find out what your browser sends to the server: https://stackoverflow.com/a/26791188/2527795 – VLL Dec 07 '20 at 10:47
  • 3
    Where is the actual c++ part within your question/code snippets? Did I miss something fundamental here? – Secundi Dec 07 '20 at 10:47
  • 1
    Look at what the request sent from the browser and from your c++ program looks like, and check what is different. – super Dec 07 '20 at 10:50
  • 1
    You can use curl with `--trace -` to see exactly what it sends and compare that to what your program is sending. – strupo Dec 07 '20 at 10:51
  • The RFC says *The multipart/form-data media type does not support any MIME header fields in parts other than Content-Type, Content-Disposition, and (in limited circumstances) Content-Transfer-Encoding. Other header fields MUST NOT be included and MUST be ignored*, and also *Senders SHOULD NOT generate any parts with a Content-Transfer-Encoding header field*. Just sayin'. – n. m. could be an AI Dec 07 '20 at 10:56
  • @ThomasSablik I have tried Postman, which does not show the http protocol of file part. I will try Wireshark, thanks. – Ted Yu Dec 08 '20 at 02:06
  • 1
    @Secundi the c++ part is all about string concatenation, to construct the http protocol text, and write it to socket by system call write, which is point of this question. "C++" in the title points to the question how to construct the protocol to post file by not using third party http library. – Ted Yu Dec 08 '20 at 02:13
  • @super I did that already, in Postman and Chrome console, neither of them show http protocol of file part , only protocol before boundary line. – Ted Yu Dec 08 '20 at 02:16
  • @strupo I will try, thanks for your advice. – Ted Yu Dec 08 '20 at 02:19
  • You may want to use some existing C++ or C libraries such as [Wt](https://www.webtoolkit.eu/wt), [libcurl](https://curl.se/libcurl/), [libonion](https://www.coralbits.com/libonion/). You should read a good book about HTTP – Basile Starynkevitch Dec 08 '20 at 06:26
  • @BasileStarynkevitch You are right. – Ted Yu Dec 08 '20 at 07:34

1 Answers1

1

Firstly, thanks for @strupo 's suggestion.

By turning on --trace option of curl and viewing the output log file, I finally fixed this problem.

In curl, it posts file by several packets:

The header:

POST /gallery/multimedia/uploadvideo HTTP/1.1
User-Agent: curl/7.29.0
Host: 192.168.0.133:8981
Accept: */*
Content-Length: 13602  # you have to calculate content length first
Expect: 100-continue   # very important line
Content-Type: multipart/form-data; boundary=------3c653d03b97f

then it waits for server response:

HTTP/1.1 100

after server responsed code 100, it sends data content, the form-data header goes first:

--------3c653d03b97f
Content-Type: video/mp4
Content-Disposition: form-data; name="file"; filename="1.mp4"
Content-Length: 6640
Content-Transfer-Encoding: 8bit

and file content follows, (in my case, a large memory is allocated, read from file and write to socket in once), and next file.

Finally the protocol should finished with boundary line:

--------3c653d03b97f--

The Content-Length should include all bytes being sent after header. The boundary should be prefixed with -- in file part. Also the \r\n everywhere should be noticed.

Ted Yu
  • 1,784
  • 1
  • 10
  • 16