While there are many scenarios when you might want to doing this either way in general, there are hardly any cases when you would want to do this directly from client since you mention ios:
Pros for uploading data via server side to AWS:
Security
As already mentioned in the other answer, having authenticated requests initially would save you much hassle from miscreants and hackers if they are trying to break stuff down. If the data is private and you are truly committed to privacy, any data leak would be easier to prevent if the system is authenticated.
Rate limiting, user quotas, etc
The added advantage of authenticated systems is that you can rate limit the requests coming from particular sources, say user, group, IP etc (app level quotas if you intend to build multiple apps around same system architecture). Building this intelligence is not that easy when you are working directly on the client side.
Audit trail
If you need to keep track of who uploaded what, when, from where, and more such information, this is once again much easier to track if you get the initial request directly on your server.
Exception handling on failure
It is quite possible to have failures that you wouldn't have easily predicted, or missing a critical bug during QA testing. Handling these server side is much more efficient, because it is under your control. When any such issues arise on the client side, you are at the mercy of your clients being able to upgrade the app. If you are dealing with this server side, additional checks could easily be placed/deployed for many such bugs, limiting the scope of the bug.
Time to go live
Again, as mentioned in the other answer, it can take a while before your update is approved. This greatly brings down your responsiveness to critical issues, and can be hard to mitigate in case of serious issues (data leak/privacy breach) leading to significant losses (financial / user trust / negative ratings etc)
The only cases when I think you would want to upload data directly from client side to AWS would be
Uploading large amounts of data, very, very frequently, without direct processing.
If uploading once costs certain amount of bandwidth and network resources, uploading it twice claims double the resources (once from client --> server
, then from server --> AWS
). So, if you upload large amounts of data frequently (think TBs daily), then you end up wasting a lot of your resources just copying data from one point to another. In such cases, it will make sense to push the data directly S3. But for this approach to work, your cost savings should be high enough to override the concerns about security and privacy, and for most applications, that is simply not the case.
You are in a walled garden
Basically, the app works only for certain pre-identified users, the app simply doesn't work for anyone else (say you were developing this for in house use in a corporate). In essence, this means having a 100% confidence in the end user's motives to use your app.
EDIT: OP asks in comments
How about server providing signed URL/cookies, and client uses these to upload to S3 or download from Cloudfront. Client still directly interacts with AWS but requires permissions controlled by server.
At first glance, it seems to me this is very workable. This blog post provides many use cases (like providing wildcard signed urls for reading) around using signed urls (though the examples are in .NET
) and more information is available at AWS docs.
Since you are going to handle the signing server side, you can easily take care of each of the points I mentioned earlier in my post (rate limiting, user quotas, audit trail etc is all workable, since the request will initially go to the server). As this answer mentions,
Signing URLs helps control who can access a given file and how long they can access it for.
Overall, this should work well for quite a few use cases.