Skip to content

Upload Service Demo Server

Alex Gotev edited this page Oct 18, 2020 · 11 revisions

Index

How to get it and run it

First of all, you need to install node.js. The following steps are described using a macOS, but they should be the same across all platforms.

  1. Open a terminal, go into a directory of your choice (In this example I do everything inside /Users/alex/temp) and

    git clone https://github.com/gotev/android-upload-service.git
    
  2. Enter the demo server directory and download its dependencies:

    cd android-upload-service/examples/server-nodejs/ && npm i
    
  3. Run the server:

    npm start
    

    and you will see an output like this:

    > nodejs-upload-server-example@1.0.0 start /Users/alex/temp/android-upload-service/examples/server-nodejs
    > node index.js
    
    Upload server started. Listening on all interfaces on port 3000
    
    The following endpoints are available for upload testing:
    
    HTTP/Multipart:              http://192.168.1.132:3000/upload/multipart
    HTTP/Multipart (Basic Auth): http://192.168.1.132:3000/upload/multipart-ba
    Binary:                      http://192.168.1.132:3000/upload/binary
    Binary (Basic Auth):         http://192.168.1.132:3000/upload/binary-ba
    401 Forbidden:               http://192.168.1.132:3000/upload/forbidden
    Validate Content Length:     http://192.168.1.132:3000/upload/validate-content-length
    
    Basic auth credentials are: {"username":"test","password":"pass"}

    Remember to keep the terminal window open to make the server run. If you close the window, it will stop.

Test multipart upload with curl

While keeping the server terminal window open, open a new terminal window and go to a directory where you have a file you want to use for upload testing.

In my case this file is called upnpresources.zip and I also add a multipart parameter mykey=myvalue. upload is the parameter name for the uploaded file. You can choose your own.

Execute:

curl -v -X POST -F mykey=myvalue -F upload=@upnpresources.zip http://192.168.1.132:3000/upload/multipart

Replace http://192.168.1.132:3000/upload/multipart with the URL of your local running demo server.

In the window where the server is running you should see something like this:

HTTP/Multipart Upload Request from: ::ffff:192.168.1.132

Received headers
----------------
host: 192.168.1.132:3000
user-agent: curl/7.64.1
accept: */*
content-length: 69164575
content-type: multipart/form-data; boundary=------------------------71581ebd6678dd8f
expect: 100-continue


Received files
--------------
[
  {
    fieldname: 'upload',
    originalname: 'upnpresources.zip',
    encoding: '7bit',
    mimetype: 'application/octet-stream',
    destination: './uploads/',
    filename: 'upload-1602929227751-263380332',
    path: 'uploads/upload-1602929227751-263380332',
    size: 69164263
  }
]

Received params
---------------
{
  "mykey": "myvalue"
}
Upload completed

and an output like this where you ran the curl command:

*   Trying 192.168.1.132...
* TCP_NODELAY set
* Connected to 192.168.1.132 (192.168.1.132) port 3000 (#0)
> POST /upload/multipart HTTP/1.1
> Host: 192.168.1.132:3000
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 69164575
> Content-Type: multipart/form-data; boundary=------------------------71581ebd6678dd8f
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Date: Sat, 17 Oct 2020 10:07:07 GMT
< Connection: keep-alive
< Content-Length: 10
<
* Connection #0 to host 192.168.1.132 left intact
{"success":true,"message":"upload completed successfully","data":{"files":[{"fieldname":"upload","originalname":"upnpresources.zip","encoding":"7bit","mimetype":"application/octet-stream","destination":"./uploads/","filename":"upload-1602929227751-263380332","path":"upload-1602929227751-263380332","size":69164263}],"params":{"mykey":"myvalue"}}}* Closing connection 0

That means the upload was successful. To get a proof of that, you may calculate the md5 of the uploaded file and the received file. In my case:

$ md5 upnpresources.zip
MD5 (upnpresources.zip) = 41971b58bc94e7b973a7e25902dbc448

$ md5 uploads/upload-1602929227751-263380332
MD5 (uploads/upload-1602929227751-263380332) = 41971b58bc94e7b973a7e25902dbc448

so it's all good!

Test binary upload with curl

While keeping the server terminal window open, open a new terminal window and go to a directory where you have a file you want to use for upload testing.

In my case this file is called upnpresources.zip and I also add a header named file-name for the demo server to know the name of my file.

Execute:

curl -v -X POST --data-binary @upnpresources.zip -H "file-name: myfile" http://192.168.1.132:3000/upload/binary

Replace http://192.168.1.132:3000/upload/binary with the URL of your local running demo server.

In the window where the server is running you should see something like this:

Binary Upload Request from: ::ffff:192.168.1.132

Received headers
----------------
host: 192.168.1.132:3000
user-agent: curl/7.64.1
accept: */*
file-name: myfile
content-length: 35190618
content-type: application/x-www-form-urlencoded
expect: 100-continue

Started binary upload of: myfile
Finished binary upload of: myfile
  in: /Users/alex/temp/android-upload-service/examples/server-nodejs/uploads/myfile

and an output like this where you ran the curl command:

*   Trying 192.168.1.132...
* TCP_NODELAY set
* Connected to 192.168.1.132 (192.168.1.132) port 3000 (#0)
> POST /upload/binary HTTP/1.1
> Host: 192.168.1.132:3000
> User-Agent: curl/7.64.1
> Accept: */*
> file-name: myfile
> Content-Length: 35190618
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: text/plain; charset=utf-8
< Content-Length: 2
< ETag: W/"2-nOO9QiTIwXgNtWtBJezz8kv3SLc"
< Date: Sat, 17 Oct 2020 10:26:00 GMT
< Connection: keep-alive
<
* Connection #0 to host 192.168.1.132 left intact
{"success":true,"data":{"filename":"myfile","uploadFilePath":"/Users/alex/temp/android-upload-service/examples/server-nodejs/uploads/myfile"}}* Closing connection 0

That means the upload was successful. To get a proof of that, you may calculate the md5 of the uploaded file and the received file. In my case:

$ md5 upnpresources.zip
MD5 (upnpresources.zip) = 41971b58bc94e7b973a7e25902dbc448

$ md5 uploads/myfile
MD5 (uploads/myfile) = 41971b58bc94e7b973a7e25902dbc448

so it's all good!

Test basic auth multipart and binary uploads with curl

Everything is the same as explained in the above sections, except for two things. When you execute the curl command you have to

  • add --user test:pass
  • use the endpoint with the -ba suffix. So multipart-ba or binary-ba

Example basic authenticated multipart curl request

curl -v -X POST --user test:pass -F mykey=myvalue -F upload=@upnpresources.zip http://192.168.1.132:3000/upload/multipart-ba

Example basic authenticated binary curl request

curl -v -X POST --user test:pass --data-binary @upnpresources.zip -H "file-name: myfile" http://192.168.1.132:3000/upload/binary-ba

Test upload with demo app

Refer to this guide: https://github.com/gotev/android-upload-service/wiki/Upload-Service-Testbed

Validate Content Length

Use this endpoint to check if the request's declared Content-Length header matches actual body content length.

Binary Request Example

curl -v -X POST --data-binary @upnpresources.zip -H "file-name: myfile" http://192.168.1.132:3000/upload/validate-content-length

Multipart Request Example

curl -v -X POST -F mykey=myvalue -F upload=@upnpresources.zip http://192.168.1.132:3000/upload/validate-content-length

The endpoint responds with HTTP 200 OK if the Content-Length is valid, otherwise HTTP 400 Bad Request. In the response you will find also expected and actual values.

Use curl to simulate poor bandwidth

curl is a fantastic tool. You can easily apply bandwidth limitations when you perform uploads by using (taken from man curl):

--limit-rate <speed>
   Specify  the  maximum transfer rate you want curl to use - for both downloads and uploads. This feature is useful if you
   have a limited pipe and you'd like your transfer not to use your entire bandwidth. To make it slower than  it  otherwise
   would be.

   The given speed is measured in bytes/second, unless a suffix is appended.  Appending 'k' or 'K' will count the number as
   kilobytes, 'm' or 'M' makes it megabytes, while 'g' or 'G' makes it gigabytes. Examples: 200K, 3m and 1G.

   If you also use the -Y, --speed-limit option, that option will take  precedence  and  might  cripple  the  rate-limiting
   slightly, to help keeping the speed-limit logic working.

   If this option is used several times, the last one will be used.

For example:

curl -vvv -X POST --limit-rate 1M -F mykey=myvalue -F upload=@large_test_file http://192.168.1.132:3000/upload/multipart

This will perform the upload using a maximum of 1 megabytes per second bandwidth.