Client-side file upload or server-side file upload. Which one is better?

Rohit Taneja
Tata 1mg Technology
4 min readApr 16, 2020
Photo by Marc-Olivier Jodoin on Unsplash

We at 1mg have moved some of our server-side file uploads to the client-side.

In this article, I’ll discuss the difference between server-side and client-side file upload and why client-side is a better choice.

What is a server-side file upload?

Server-side means that the action i.e file upload takes place on the application server

Client i.e the browser(Chrome) or Apps (Android, iOS) uploads the file content to the website’s server

Server uploads the file content to a third party file storage utility (AWS S3)

What is a client-side file upload?

Client-side means that the action is done on the user’s device

Client requests for presigned URL data with authentication info from server

Client uploads the file to AWS S3 with the above authentication info

Client sends the file URL received from the above S3 request to the website’s server

A file upload request flow:

A file upload request flow

Pros of client-side approach:

As we don’t have the file data and have just the URL of the file,
we don’t have to carry the file data across multiple hops which has the following pros:

  • Lower memory consumption
  • Lower CPU consumption
  • Lower file read/write resources consumption
  • Faster uploads as uploads now will go directly to S3
  • Cheaper as outbound traffic from the server accrues charges

Cons of client-side approach:

  • It comes with some security concerns discussed in the next section
  • Number of API requests from client are 3 now instead of 1 in server-side
  • Clients will also have to make changes if in future we want to change the third party file utility from S3 to others. This becomes difficult in case of apps (Android, iOS) as in this cases users will have to update the app to get new changes

Security concerns in client-side file upload and their solutions:

Concern: User trying to upload a huge file (say size ≥ 20MB)
Solution: We can set file size limit in the presigned URL

Concern: User trying to upload a different file type
Solution: We can define allowed file type in presigned URL. Example jpeg, png, etc

Concern: Presigned URL credentials got leaked or being used multiple times
Solution: We can set expiry time of the presigned URL

Concern: User is abusing presigned URL get API and uploading files to AWS S3
Solution: We can rate-limit user in the presigned URL API call

Some important points to consider:

  • A catch that got me half a day to figure out was that AWS API expects file parameter to be present at the end of the HTTP request and if we send it before the end then AWS ignores all the parameters after the file parameter
  • The response of this curl request will be in XML and there is no way to get the response in JSON. So we have to convert the response from XML to JSON if required
  • If you have multiple files to upload, you can upload them parallelly to save time

How to get started

python3.7 -m venv new_virtual_env
pip3 install boto3
  • Install requests package for making HTTP requests
pip3 install requests
  • Create AWS account: The free tier usage of S3 is more than enough for testing
  • Create a new bucket in S3
    You’ll have to set setting for Block all public access OFF if you want the files to be publicly accessible
  • As a security measure you can add CORS policy to allow only your domains from web browsers to make PUT/POST HTTP requests to S3
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://www.yourdomain.com</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
  • Create Access keys for S3 upload
  • Python code snippet to get presigned url data and to test presigned upload
  • Sample Curl request for uploading file from Presigned data:
curl -L -X POST 'https://test.s3.amazonaws.com/' -H 'Content-Type: application/x-www-form-urlencoded' -F 'Content-Type=Content-Type' -F 'acl=acl' -F 'key=key' -F 'policy=policy' -F 'success_action_status=success_action_status' -F 'x-amz-algorithm=x-amz-algorithm' -F 'x-amz-credential=x-amz-credential' -F 'x-amz-date=x-amz-date' -F 'x-amz-signature=x-amz-signature' -F 'file=@/path_to_testfile.png'

Conclusion:

Although client-side approach has cons but they either have workarounds or are not of much impact so the pros overweigh them and hence client-side approach is a better approach.

Thanks for stopping by.

I hope you enjoyed the read and learned something.
Please feel free to share your views and feedback in the comments section.

If you found this helpful, please clap and share the article. Let other people also learn from this article.

--

--