Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GuruSP - Solucionando o problema de Uploads em...
Search
Rafael Macedo
June 21, 2014
Programming
120
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GuruSP - Solucionando o problema de Uploads em Apps no Heroku
Rafael Macedo
June 21, 2014
More Decks by Rafael Macedo
See All by Rafael Macedo
Modularização de código JS
macedorafael
0
250
TDC 2014 - Solucionando o problema de Uploads em Apps no Heroku
macedorafael
1
170
Aplicações Realtime com XMPP
macedorafael
3
220
Web in the cloud with ruby
macedorafael
2
400
Other Decks in Programming
See All in Programming
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
580
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
690
torikago - Ruby::Boxで照らすモジュラモノリスの実行境界
se4weed
1
370
Go 1.27 における memory allocation の高速化
andpad
0
170
テーブルをDELETEした
yuzneri
0
140
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
180
改善しないと、タスクが回らない。 “てんこ盛りポジション” を引き継いだ情シスの、入社3ヶ月の業務改善録
krm963
0
260
運用ダッシュボードの設計を誰も教えてくれないのだけどみなさんどうしてるんですか? - チームに監視するという文化を根付かせるための第一歩を踏みたい -
satoshi256kbyte
1
120
SlackアプリとLambdaの 連携を構築した話
pawn_4_s
1
120
言葉の格闘技のススメ~紙とペンと言葉から始める、キャリアの描き方~
progresscicada
2
150
What's New in Android 2026
veronikapj
0
260
AIが無かった頃の素敵な出会いの話
codmoninc
1
430
Featured
See All Featured
Practical Orchestrator
shlominoach
191
12k
Darren the Foodie - Storyboard
khoart
PRO
3
3.6k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.3k
Exploring anti-patterns in Rails
aemeredith
3
460
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
210
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
240
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
790
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
650
ラッコキーワード サービス紹介資料
rakko
1
4.3M
KATA
mclloyd
PRO
35
15k
Transcript
Solucionando o problema de Uploads em Apps no Heroku
@macedorafael http://github.com/macedo Rafael Macedo
@macedorafael http://github.com/macedo Macedo
backend…
…com chapéu de front
None
None
None
“O que pode dar errado num mero upload de uma
foto?”
None
30 segundos
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser
None
…
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
! ! ! ! Unicorn Rails AWS S3 Image Magick
Browser ! ! ! ! Resque/Sidekiq Worker
heroku addons
None
Blitline
Blitline Transloadit
Blitline Transloadit Cloudinary
Blitline Transloadit Cloudinary ✔
http://cloudinary.com
None
None
upload
None
•JPG, PNG, GIF, BMP, ICO, TIFF and PDF
•JPG, PNG, GIF, BMP, ICO, TIFF and PDF •Secure HTTP
upload API
•JPG, PNG, GIF, BMP, ICO, TIFF and PDF •Secure HTTP
upload API •Upload from your server or directly from the browser
storage
None
•Cloud-based persistent storage
•Cloud-based persistent storage •Highly available redundant storage
•Cloud-based persistent storage •Highly available redundant storage •S3
delivery
None
•Fast delivery (CDN)
•Fast delivery (CDN) •Smart caching
image transformation/ manipulation
None
resize
resize filter
resize filter crop
resize filter crop rotate
resize filter crop rotate face detection
resize filter crop rotate face detection chained transformation …
{"public_id"=>"fe23qemppmcorq0grmfv", "version"=>1403326723, "signature"=>"4e1a7bb2e3f3eb05eed25eed10cb09807561a764", "width"=>533, "height"=>300,
"format"=>"jpg", "resource_type"=>"image", "created_at"=>"2014-‐06-‐21T04:58:43Z", "bytes"=>13895, "type"=>"upload", "etag"=>"30b1c1b426db36b8e8c12d15d629fdb5", "url"=>"http://res.cloudinary.com/hxjx3jqm7/image/upload/v1403326723/ fe23qemppmcorq0grmfv.jpg", "secure_url"=>"https://res.cloudinary.com/hxjx3jqm7/image/upload/v1403326723/ fe23qemppmcorq0grmfv.jpg"}
{"public_id"=>"fe23qemppmcorq0grmfv", "version"=>1403326723, "signature"=>"4e1a7bb2e3f3eb05eed25eed10cb09807561a764", "width"=>533, "height"=>300,
"format"=>"jpg", "resource_type"=>"image", "created_at"=>"2014-‐06-‐21T04:58:43Z", "bytes"=>13895, "type"=>"upload", "etag"=>"30b1c1b426db36b8e8c12d15d629fdb5", "url"=>"http://res.cloudinary.com/hxjx3jqm7/image/upload/v1403326723/ fe23qemppmcorq0grmfv.jpg", "secure_url"=>"https://res.cloudinary.com/hxjx3jqm7/image/upload/v1403326723/ fe23qemppmcorq0grmfv.jpg"}
http://res.cloudinary.com/hxjx3jqm7/image/ upload/v1403326723/ fe23qemppmcorq0grmfv.jpg
http://res.cloudinary.com/hxjx3jqm7/image/ upload/v1403326723/ fe23qemppmcorq0grmfv.jpg
http://res.cloudinary.com/hxjx3jqm7/image/ upload/v1403326723/ fe23qemppmcorq0grmfv.jpg http://res.cloudinary.com/hxjx3jqm7/image/ upload/w_160,h_160,c_thumb,g_face/ fe23qemppmcorq0grmfv.jpg
http://res.cloudinary.com/hxjx3jqm7/image/ upload/v1403326723/ fe23qemppmcorq0grmfv.jpg http://res.cloudinary.com/hxjx3jqm7/image/ upload/w_160,h_160,c_thumb,g_face/ fe23qemppmcorq0grmfv.jpg
None
gem 'cloudinary'
# config/cloudinary.yml development: cloud_name:
“sample” api_key: “912739217312873” api_secret: “a123=asdaszad34dsf”
cl_image_tag(“e23qemppmcorq0grmfv.jpg”,
width: 160, height: 160, crop: fill, effect: ”sepia” )
cl_image_tag(“e23qemppmcorq0grmfv.jpg”,
effect: )
cl_image_tag(“e23qemppmcorq0grmfv.jpg”,
width: 100, height: 150, effect: :pixelate)
cl_image_tag(“e23qemppmcorq0grmfv.jpg”,
cl_image_tag(“e23qemppmcorq0grmfv.jpg”,
class ImageUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave
version :standard do process :resize_to_fill => [100, 150, :fill] cloudinary_transformation quality: 80 end version :thumbnail do process :eager => true cloudinary_transformation transformation: [ { width: 100, height: 100, crop: :thumb, gravity: :face }, { overlay: ”watermark”, width: 30, hgravity: :south_east, x: 5, y: 5 } ] end end
class ImageUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave
version :standard do process :resize_to_fill => [100, 150, :fill] cloudinary_transformation quality: 80 end version :thumbnail do process :eager => true cloudinary_transformation transformation: [ { width: 100, height: 100, crop: :thumb, gravity: :face }, { overlay: ”watermark”, width: 30, hgravity: :south_east, x: 5, y: 5 } ] end end
class ImageUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave
version :standard do process :resize_to_fill => [100, 150, :fill] cloudinary_transformation quality: 80 end version :thumbnail do process :eager => true cloudinary_transformation transformation: [ { width: 100, height: 100, crop: :thumb, gravity: :face }, { overlay: ”watermark”, width: 30, hgravity: :south_east, x: 5, y: 5 } ] end end
class ImageUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave
version :standard do process :resize_to_fill => [100, 150, :fill] cloudinary_transformation quality: 80 end version :thumbnail do process :eager => true cloudinary_transformation transformation: [ { width: 100, height: 100, crop: :thumb, gravity: :face }, { overlay: ”watermark”, width: 30, hgravity: :south_east, x: 5, y: 5 } ] end end
class ImageUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave
version :standard do process :resize_to_fill => [100, 150, :fill] cloudinary_transformation quality: 80 end version :thumbnail do process :eager => true cloudinary_transformation transformation: [ { width: 100, height: 100, crop: :thumb, gravity: :face }, { overlay: ”watermark”, width: 30, hgravity: :south_east, x: 5, y: 5 } ] end end
class ImageUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave
version :standard do process :resize_to_fill => [100, 150, :fill] cloudinary_transformation quality: 80 end version :thumbnail do process :eager => true cloudinary_transformation transformation: [ { width: 100, height: 100, crop: :thumb, gravity: :face }, { overlay: ”watermark”, width: 30, hgravity: :south_east, x: 5, y: 5 } ] end end
class Advertisement < ActiveRecord::Base ... mount_uploader
:image, ImageUploader ... end
= form_for(:advertisement) do |f| = f.hidden_field(:image_cache)
= f.file_field(:image)
None
# app/assets/javascripts/application.js //= require cloudinary
= form_for(:advertisement) do |f| ...
= cloudinary_js_config = f.cl_image_upload(:image) ..
= form_for(:advertisement) do |f| ...
= cloudinary_js_config = f.cl_image_upload(:image) ..
= form_for(:advertisement) do |f| ...
= cloudinary_js_config = f.cl_image_upload(:image) ..
None
$$$
None
10 GB Storage
10 GB Storage 40 GB Bandwidth
Cloudinary
$35
S3
$7
None
None
$7
$42
Conclusão
“O que pode dar errado num mero upload de uma
foto?”
Muita coisa!
None
Processamento background
Processamento background Direct Upload
None
OBRIGADO
OBRIGADO ?