How to speed up image uploading carrierwave and Rails4 - ruby-on-rails

I am working with Rails4 and carrierwave, uploading the images and files to S3. But it's taking much time and very slow. How to handle this situation to speed up the server speed!!!
How to handle this using Background Jobs and Handle request from lot of users.
Also getting images is very slow into my application!!!
Can you suggest me how to achieve Rails severe works fast while uploading files?

You might consider uploading directly from the client to S3 via Ajax. This would nearly completely take your server out of the mix.
Uploading Image to Amazon s3 with HTML, javascript & jQuery with Ajax Request (No PHP)
This is a well documented concept elsewhere online.
Amazon S3 now has notifications for newly created objects.
http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html
You could drop the upload notifications into an Amazon SQS queue. You could then use a gem like Fog to create a background worker to pull events off the queue to create or update records in the database to reflect the newly completed upload.
https://github.com/fog/fog
Regardless of the solution, if you're uploading big files, it's likely your local network's upload speed that is the bottleneck.

Related

What is ActiveStorage's 'attach' doing behind the scenes when files are uploaded to a service as like AWS?

I can't seem to find a detailed explanation of what process the attach method initialises when uploading a file (not direct upload) to a configured service such as Amazon S3.
Does the file get uploaded to the application server temporarily first while a job is created to upload it to S3?
If so, is there a job to clear it out or is it removed once the job uploading it to S3 returns successfully?
What if that job fails, does it just replace itself? etc etc
I think I understand the process for direct uploads and why a bit of manual error handling needs to be done, but I'd like to know exactly how ActiveStorage handles uploads through the application server and I can't seem to find solid documentation on this.

fb_graph upload photo from base64 encoded string

I'm receiving attachments from postmarkapp (described here: http://developer.postmarkapp.com/developer-inbound-parse.html#attachments).
I want to upload those photos to facebook using fb_graph (https://github.com/nov/fb_graph) using its photo! method (https://github.com/nov/fb_graph/wiki/Photo-and-Album).
This is easy and works fine when testing by specifying a :source like in the examples from an actual file.
However I'm trying to not write out to a file but instead just convert the base64 encoded string to StringIO and pass that as the :source argument. This doesn't work and I get this error:
ruby
FbGraph::InvalidRequest: OAuthException :: (#324) Requires upload file
The reason I don't want to write out a file is because I'm using heroku and delayed_job so I'm not sure if a file I write out will still be around when the job is processed. That would be nice however since my current plan is to store the images in the db with delayed job.
Thanks.
I couldn't find a way to make this work with heroku without first uploading it to mongohq with gridfs. You can't use the cedar ephemeral file system because those files, written during a controller action, won't be visible to your delayed_job worker.
So even though it sucks I do this;
Receive upload from postmarkapp (blocks one dyno)
Write to mongohq using grid fs (this involves one upload which blocks one dyno)
Queue job using delayed_job
Read back from mongohq (blocks one worker while downloading)
Re-upload to FB when posting
So why not just post directly to facebook if I'm going to incur that initial blocking cost of uploading to mongohq anyway? Because that upload is way faster than uploading to FB for reasons unkonwn.
The right answer on heroku is to have a node.js dyno handling these callbacks from postmark so the dyno isn't blocked during either the read from postmark or the write to mongohq (or facebook) then to do some extra work to have the node app interact with the rails app to stay synced.

How to post images directly to s3 on a heroku app from a json request?

I have a rails app hosted on heroku and a mobile app made with rhodes.
I'd like to send images from the mobile app to my rails app using an HTTP POST request. Since heroku doesn't allow you to store files, I'm using amazon s3.
I can't send the file from heroku to s3 because it takes more than 30 seconds and causes a timeout. I've seen plenty of examples of uploading a file direct to s3 when the user has a form, but this obviously won't work in this case.
I tried using the suggestion here:
rails 3, heroku, aws-s3, simply trying to upload a file to S3 that is POSTed (http/multipart) to our app
but I still get a 503 request timeout.
I don't want to put my amazon s3 keys on the app.
Right now, I feel like my only option is to host my app on EC2 which I would rather not do as I like the simplicity of Heroku.
Also, it seems strange that these uploads would take so long regardless. I'm only posting images from a mobile phone camera, so they're not huge files.
I was getting the same error in a project in my job. Some people says that the only way to solve this is by uploading files directly to the S3 bucket. This is difficult in our case, because we are using Paperclip Gem for Rails and different size versions of the image.
Some other people says that "The Heroku timeout is a set in stone thing that you need to work around. Direct upload to S3 is the only option, with some sort of post-upload processing required", so I recomend to do the next:
Maybe this is not a solution but, it could be very useful, it was for me in a Rails App:
Worker Dynos, Background Jobs and Queueing
Perhaps you should move this heavy lifting into a background job which can run asynchronously from your web request.
Regards!
So I finally figured out how to do this.
After lots of back and forth with AWS reps and Cloudfiles reps and pulling my hair out, I realized it would be a lot less work to just get another rails server that could write to the filesystem.
So, I started another rails app on openshift. It's just as easy as Heroku to get started (in fact, I might consider moving my rails app there, but it's too new for my taste right now and doesn't have the community around it that Heroku does).
Then, I just had to have communications between my two rails apps.
I know it's not the best/scalable/elegant fix, but it got the job done, and that's what matters in the end!

how to get bytes loaded to server using rails paperclip gem?

i am using paperclip gem to upload images on the server side, i need to get updated with the bytes loaded on server through the upload process.
my aim is to update the progress bar accordingly. how do I do this?
You can only do this by using a Flash-based uploading tool which has direct access to the file and the upload stream. Just integrate it with Paperclip (and there are a ton of examples on google showing how to)
I would recommend one of these:
http://plupload.com/
http://www.uploadify.com/

Why would you upload assets directly to S3?

I have seen quite a few code samples/plugins that promote uploading assets directly to S3. For example, if you have a user object with an avatar, the file upload field would load directly to S3.
The only way I see this being possible is if the user object is already created in the database and your S3 bucket + path is something like
user_avatars.domain.com/some/id/partition/medium.jpg
But then if you had an image tag that tried to access that URL when an avatar was not uploaded, it would yield a bad result. How would you handle checking for existence?
Also, it seems like this would not work well for most has many associations. For example, if a user had many songs/mp3s, where would you store those and how would you access them.
Also, your validations will be shot.
I am having trouble thinking of situations where direct upload to S3 (or any cloud) is a good idea and was hoping people could clarify either proper use cases, or tell me why my logic is incorrect.
Why pay for storage/bandwidth/backups/etc. when you can have somebody in the cloud handle it for you?
S3 (and other Cloud-based storage options) handle all the headaches for you. You get all the storage you need, a good distribution network (almost definitely better than you'd have on your own unless you're paying for a premium CDN), and backups.
Allowing users to upload directly to S3 takes even more of the bandwidth load off of you. I can see the tracking concerns, but S3 makes it pretty easy to handle that situation. If you look at the direct upload methods, you'll see that you can force a redirect on a successful upload.
Amazon will then pass the following to the redirect handler: bucket, key, etag
That should give you what you need to track the uploaded asset after success. Direct uploads give you the best of both worlds. You get your tracking information and it unloads your bandwidth.
Check this link for details: Amazon S3: Browser-Based Uploads using POST
If you are hosting your Rails application on Heroku, the reason could very well be that Heroku doesn't allow file-uploads larger than 4MB:
http://docs.heroku.com/s3#direct-upload
So if you would like your users to be able to upload large files, this is the only way forward.
Remember how web servers work.
Unless you're using a sort of async web setup like you could achieve with Node.JS or Erlang (just 2 examples), then every upload request your web application serves ties up an entire process or thread while the file is being uploaded.
Imagine that you're uploading a file that's several megabytes large. Most internet users don't have tremendously fast uplinks, so your web server spends a lot of time doing nothing. While it's doing all of that nothing, it can't service any other requests. Which means your users start to get long delays and/or error responses from the server. Which means they start using some other website to get the same thing done. You can always have more processes and threads running, but each of those costs additional memory which eventually means additional $.
By uploading straight to S3, in addition to the bandwidth savings that Justin Niessner mentioned and the Heroku workaround that Thomas Watson mentioned, you let Amazon worry about that problem. You can have a single-process webserver effectively handle very large uploads, since it punts that actual functionality over to Amazon.
So yeah, it's more complicated to set up, and you have to handle the callbacks to track things, but if you deal with anything other than really small files (and even in those cases), why cost yourself more money?
Edit: fixing typos

Resources