SlideShare ist ein Scribd-Unternehmen logo
1 von 94
Downloaden Sie, um offline zu lesen
File Upload 2015
@choonkeatā€Ø
choonkeat.com
jollygoodcode.com
Howā€™s that predeļ¬ned styles
doing for you?
has_attached_file :asset, styles: {
thumb: "100x100#"
}
Howā€™s that predeļ¬ned styles
doing for you?
has_attached_file :asset, styles: {
thumb: "100x100#",
medium: "320x>"
}
Howā€™s that predeļ¬ned styles
doing for you?
has_attached_file :asset, styles: {
thumb: "100x100#",
medium: "320x>",
large: "1024x>"
}
Howā€™s that predeļ¬ned styles
doing for you?
has_attached_file :asset, styles: {
thumb: "100x100#",
medium: "320x>",ā€Ø
big: "640x>",
large: "1024x>"
}
Names starting to lose
meaningā€¦
Howā€™s that predeļ¬ned styles
doing for you?
has_attached_file :asset, styles: {
thumb: "100x100#", thumb2x: "200x200#",
medium: "320x>", medium2x: "640x>",ā€Ø
big: "640x>", big2x: "1280x>",
large: "1024x>", large2x: "2048x>"
}
Howā€™s that predeļ¬ned styles
doing for you?
has_attached_file :asset, styles: {
thumb: "100x100#", thumb2x: "200x200#",
medium: "320x>", medium2x: "640x>",ā€Ø
big: "640x>", big2x: "1280x>",
large: "1024x>", large2x: "2048x>"
}
Reprocess all the production ļ¬les, each
time, we make changes.
404 while rake runs or do at midnight?
Howā€™s that transformation
juggling doing for you?
Howā€™s that transformation
juggling doing for you?
class MyUploader < CarrierWave::Uploader::Base
version :thumb do
process resize_to_fill: [280, 280]
end
version :small_thumb, from_version: :thumb do
process resize_to_fill: [20, 20]
end
end
Howā€™s that transformation
juggling doing for you?
class MyUploader < CarrierWave::Uploader::Base
version :thumb do
process resize_to_fill: [280, 280]
end
version :small_thumb, from_version: :thumb do
process resize_to_fill: [20, 20]
end
end
Did your users wait in the foreground
or background?
Howā€™s that ļ¬le path conļ¬g
doing for you?
Howā€™s that ļ¬le path conļ¬g
doing for you?
class Avatar < ActiveRecord::Base
has_attached_file :image,ā€Ø
url: '/system/:class/:attachment/:id/:hash-:style.:extension',
hash_secret: Rails.application.secrets.paperclip
end
Howā€™s that ļ¬le path conļ¬g
doing for you?
class Avatar < ActiveRecord::Base
has_attached_file :image,ā€Ø
url: '/system/:class/:attachment/:id/:hash-:style.:extension',
hash_secret: Rails.application.secrets.paperclip
end
You sure this is the format?
Or will they need to change?
Howā€™s that ļ¬le path conļ¬g
doing for you?
class Avatar < ActiveRecord::Base
has_attached_file :image,ā€Ø
url: '/system/:class/:attachment/:id/:hash-:style.:extension',
hash_secret: Rails.application.secrets.paperclip
end
Howā€™s that ļ¬le path conļ¬g
doing for you?
class Avatar < ActiveRecord::Base
has_attached_file :image,ā€Ø
url: '/system/:class/:attachment/:id/:hash-:style.:extension',
hash_secret: Rails.application.secrets.paperclip
end
Howā€™s that ļ¬le path conļ¬g
doing for you?
CarrierWave.configure do |config|
config.permissions = 0666
config.directory_permissions = 0777
config.storage = :file
end
Howā€™s that ļ¬le path conļ¬g
doing for you?
CarrierWave.configure do |config|
config.permissions = 0666
config.directory_permissions = 0777
config.storage = :file
end
Did you conļ¬gure your MySQL
data ļ¬le in your app too?
Howā€™s that ļ¬le path conļ¬g
doing for you?
class Avatar < ActiveRecord::Base
self.table = {
name: "avatars",
data: "/var/lib/mysql/data/avatars.MYD",
index: "/var/lib/mysql/data/avatars.MYI"
}
end
Did you conļ¬gure your MySQL
data ļ¬le in your app too?
Howā€™s that form validation
error dance doing for you?
Howā€™s that form validation
error dance doing for you?
ā€¢ User chooses a ļ¬le
ā€¢ Submit & wait for ļ¬le to upload āŒ›ā€¦
ā€¢ Validation error: ā€œUsername is already taken!ā€
ā€¢ Re-render form
Howā€™s that form validation
error dance doing for you?
ā€¢ User chooses a ļ¬le
ā€¢ Submit & wait for ļ¬le to upload āŒ›ā€¦
ā€¢ Validation error: ā€œUsername is already taken!ā€
ā€¢ Re-render form
Where dat ļ¬le go?
Howā€™s that form validation
error dance doing for you?
http://stackoverļ¬‚ow.com/questions/5198602/not-losing-paperclip-attachment-when-model-cannot-be-saved-due-to-validation-err
Closed: Wonā€™t Fix
Howā€™s that form validation
error dance doing for you?
http://stackoverļ¬‚ow.com/questions/5198602/not-losing-paperclip-attachment-when-model-cannot-be-saved-due-to-validation-err
Howā€™s that form validation
error dance doing for you?
http://stackoverļ¬‚ow.com/questions/5198602/not-losing-paperclip-attachment-when-model-cannot-be-saved-due-to-validation-err
Answer: use CarrierWave
Howā€™s that form validation
error dance doing for you?
Howā€™s that form validation
error dance doing for you?
ā€œIs there a standard
approach? This seems like
a very common use case.ā€
Howā€™s the schema pollution
doing for you?
Howā€™s the schema pollution
doing for you?
class StoreMetadata < ActiveRecord::Migration
def change
add_column :users, :profile_image_filename, :string
add_column :users, :profile_image_size, :integer
add_column :users, :profile_image_content_type, :string
end
end
Howā€™s the schema pollution
doing for you?
class StoreMetadata < ActiveRecord::Migration
def change
add_column :users, :profile_image_filename, :string
add_column :users, :profile_image_size, :integer
add_column :users, :profile_image_content_type, :string
end
end
Howā€™s that multiple ļ¬les
doing for you?
Howā€™s that multiple ļ¬les
doing for you?
class Post < ActiveRecord::Base
has_many :images, dependent: :destroy
end
Howā€™s that multiple ļ¬les
doing for you?
class Post < ActiveRecord::Base
has_many :images, dependent: :destroy
end
class Image < ActiveRecord::Base
belongs_to :post
attachment :file
end
Howā€™s that multiple ļ¬les
doing for you?
class Post < ActiveRecord::Base
has_many :images, dependent: :destroy
end
class Image < ActiveRecord::Base
belongs_to :post
attachment :file
end
Howā€™s that multiple ļ¬les
doing for you?
class Post < ActiveRecord::Base
has_many :images, dependent: :destroy
end
class Image < ActiveRecord::Base
belongs_to :post
attachment :file
end
Is this what you want or just
what youā€™re accustomed to?
Howā€™s Amazon Lambda
doing for you?
ā€¢ User chooses a ļ¬le
ā€¢ Submit & wait for ļ¬le to upload āŒ›ā€¦
ā€¢ Success!
ā€¢ Render page with thumbnailā€¦
How many thumbnails -
404?
Howā€™s Amazon Lambda
doing for you?
ā€¢ User chooses a ļ¬le
ā€¢ Submit & wait for ļ¬le to upload āŒ›ā€¦
ā€¢ Success!
ā€¢ Render page with thumbnailā€¦
Direct upload to AWS?
Cancel form submit -
delete ļ¬les & thumbnails?
Deep integration &
assumption
Howā€™s Dragonļ¬‚y
doing for you?
http://markevans.github.io/dragonļ¬‚y/
Howā€™s reļ¬le
doing for you?
https://github.com/reļ¬le/reļ¬le
http://thecooperreview.com/10-tricks-appear-smart-meetings/
10 Tricks to Appear Smart
During Meetings
Take a step back
Take a step back
ā€¢ We want to store a bunch of attributes in a model
ā€¢ e.g. Title, Body, Tags, Photoā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
Take a step back
{photo}
{title}
{body}
Take a step back
<img src={photo}>
<h1>{title}</h1>
{body}
Take a step back
ā€¢ Why should photo be a disproportionately
complicated attribute in my Article model?
ā€¢ stored ļ¬le path
ā€¢ conversion
ā€¢ background job
ā€¢ aws conļ¬g
ā€¢ clean up on delete
Take a step back
ā€¢ Why should photo be a disproportionately
complicated attribute in my Article model?
ā€¢ stored ļ¬le path
ā€¢ conversion
ā€¢ background job
ā€¢ validation error dance
ā€¢ aws conļ¬g
Take a step back
ā€¢ Frankly photo_url is best; least intrusiveā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
Take a step back
ā€¢ Frankly photo_url is best; least intrusive
ā€¢ Problems
ā€¢ Remote url 404? (not exclusive to your app)
ā€¢ Asking users to give us a URL is a hard sell
ā€¢ Need to render other sizes
ā€¢ Filter by meta data
Take a step back
ā€¢ Frankly photo_url is best; least intrusive
ā€¢ Problems
ā€¢ Remote url 404? (not exclusive to your app)
ā€¢ Asking users to give us a URL is a hard sell
ā€¢ Need to render other sizes
ā€¢ Filter by meta data
Take a step back
ā€¢ Frankly photo_url is best; least intrusive
ā€¢ Problems
ā€¢ Remote url 404? (not exclusive to your app)
ā€¢ Asking users to give us a URL is a hard sell
ā€¢ Need to render other sizes
ā€¢ Filter by meta data
Take a step back
ā€¢ Frankly photo_url is best; least intrusive
ā€¢ Solutions
ā€¢ Exclusive server for your app
ā€¢ Upload to that server
ā€¢ On-the-ļ¬‚y resize based on URL
ā€¢ Store url with meta data: photo_json instead?
Just add server
ā€¢ PostgreSQL, MySQL
ā€¢ Redis
ā€¢ Memcached
ā€¢ SMTP server (Mail)ā€Ø
ā€Ø
ā€Ø
ā€Ø
You are already
Generic server to do
specialised work
Not speciļ¬c to your
business logic
ā€¢ Not a new pattern
ā€¢ Mostly commercial servicesā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€¢ Maybe it has to be Free & Open Source to become
a default pattern
Image server
Want
ā€¢ Move the ā€œconcernā€ out of my app
ā€¢ photo is a regular attribute
ā€¢ conļ¬gure my app & forget it existā€Ø
ā€Ø
ā€Ø
ā€Ø
Want
ā€¢ Move the ā€œconcernā€ out of my app
ā€¢ photo is a regular attribute
ā€¢ conļ¬gure my app & forget it existā€Ø
ā€Ø
ā€Ø
ā€Ø What would my app look
like in a better world?
My app: Bare minimum
create_table "users" do |t|
t.string "name"
t.json "avatar"
t.json "photos"
end
My app: Bare minimum
create_table "users" do |t|
t.string "name"
t.json "avatar"
t.json "photos" # multiple files in a column
end
My app: Bare minimum
Image serverRails appBrowser
{ avatar: #<File..> }
My app: Bare minimum
Image serverRails appBrowser
{ avatar: #<File..> }
{ā€œpathā€:ā€œx.jpgā€,
ā€œgeometryā€:ā€œ200x600ā€}
#<File..>
My app: Bare minimum
Image serverRails appBrowser
{ā€œpathā€:ā€œx.jpgā€,
ā€œgeometryā€:ā€œ200x600ā€}
#<File..>
user.avatar={ā€œpathā€: ā€œx.jpgā€ā€¦}
user.save
<img src=ā€œx.jpgā€>
{ avatar: #<File..> }
My app: Bare minimum
Image serverRails appBrowser
{ā€œpathā€:ā€œx.jpgā€,
ā€œgeometryā€:ā€œ200x600ā€}
<img src=ā€œx.jpgā€>
#<File..>
GET x.jpg
#<File..>
user.avatar={ā€œpathā€: ā€œx.jpgā€ā€¦}
user.save
{ avatar: #<File..> }
My app: Bare minimum
ā€¢ Browser render <file> ļ¬eld; regular form submit
ā€¢ Receive binary param, uploads to attache server
and stores the json response instead
ā€¢ Your app render <img src> requesting for image in
certain size, e.g. http://example/200x/
file.pngā€Ø
ā€Ø
ā€Ø
Image serverRails appBrowser
#<File..>
{ā€œpathā€:ā€œx.jpgā€,
ā€œgeometryā€:ā€œ200x600ā€}
Progressive Enhancement
Image serverRails appBrowser
#<File..>
{ā€œpathā€:ā€œx.jpgā€,
ā€œgeometryā€:ā€œ200x600ā€}
Progressive Enhancement
{ avatar: {ā€œpathā€:ā€œx.jpgā€, ā€¦ }
{ avatar: {ā€œpathā€:ā€œx.jpgā€, ā€¦ }
Image serverRails appBrowser
#<File..>
{ā€œpathā€:ā€œx.jpgā€,
ā€œgeometryā€:ā€œ200x600ā€}
user.avatar={ā€œpathā€: ā€œx.jpgā€ā€¦}
user.save
<img src=ā€œx.jpgā€>
Progressive Enhancement
ā€¢ Browser render <file> ļ¬eld; regular form submit
ā€¢ Receive binary param, uploads to attache server
and stores the json response instead
ā€¢ Your app render <img src> requesting for image in
certain size, e.g. http://example/200x/
file.pngā€Ø
ā€Ø
ā€Ø
Progressive Enhancement
ā€¢ Browser render <file> ļ¬eld; regular form submit
ā€¢ Receive binary param, uploads to attache server
and stores the json response instead
ā€¢ Your app render <img src> requesting for image in
certain size, e.g. http://example/200x/
file.pngā€Ø
ā€Ø
ā€Ø
ā€¢ JS upload directly to attache server; ā€œDirect uploadā€ in
AWS parlance
ā€¢ No binary in params; receive and store json attribute
Progressive Enhancement
ā€¢ When after_update & after_destroy
removes obsolete ļ¬le from attache via delete API
ā€¢ Just use Ruby; just use your framework
ā€¢ Pre-render multiple sizes
ā€¢ fetch the urls, server will generate and cache
ā€¢ Validation
ā€¢ validating a regular json attribute
How do Iā€¦
ā€¢ Move the ā€œconcernā€ out of my app
ā€¢ photo is a regular attribute
ā€¢ conļ¬gure my app & forget it existā€Ø
ā€Ø
ā€Ø
ā€Ø
Want (contā€™d)
Want (contā€™d)
ā€¢ Move the ā€œconcernā€ out of my app
ā€¢ photo is a regular attribute
ā€¢ conļ¬gure my app & forget it exist
ā€¢ Separate, standalone server
ā€¢ Minimal / zero ongoing administration
Want (contā€™d)
ā€¢ Move the ā€œconcernā€ out of my app
ā€¢ photo is a regular attribute
ā€¢ conļ¬gure my app & forget it exist
ā€¢ Separate, standalone server
ā€¢ Minimal / zero ongoing administration
How does this
server work?
Attache File Server
ā€¢ HTTP server with simple APIs
ā€¢ upload
ā€¢ download
ā€¢ delete
ā€¢ Rack app + ImageMagick
ā€¢ Go? Node? C++? PHP?
ā€¢ GraphicsMagick? MyResizer.bash?
ā€¢ Uploaded ļ¬les are stored locally
ā€¢ Resize local ļ¬le on-the-ļ¬‚y
ā€¢ conļ¬gurable pool size to limit concurrent resizing
ā€¢ Sync upload to cloud storage
ā€¢ 2 hop problem vs complexity
ā€¢ Fixed local storage, purge LRU (zero maintenance)
ā€¢ Spin up new fresh servers anytimeā€¦ ā€Ø
Attache File Server
ā€¢ When requested ļ¬le does not exist locally
ā€¢ fetch from cloud storage & write locally
ā€¢ resume operationsā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
Attache File Server
ā€¢ Remove obsolete ļ¬le is ā€œbest effortā€
ā€¢ If photo delete failed, do you Error 500 or stop the
world?ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€¢ OCDs can schedule rake task remove dangling ļ¬les?
Attache File Server
ā€¢ Caching in production
ā€¢ Browser ā†’ CDN ā†’ Varnish ā†’ Disk ā†’ Cloudā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
ā€Ø
Attache File Server
Demo
https://attache-demo.herokuapp.com/
https://github.com/choonkeat/attache_api
ATTACHE_URL=http://localhost:9292
ATTACHE_SECRET_KEY=topsecret
rake
Compatibility Check
tus.io
ā€¢ Open protocol for resumable uploads built on HTTP
ā€¢ Perfect for mobile apps
ā€¢ Rack middleware implemented in choonkeat/
attache#10
Responsive Images with
Client Hints
http://blog.imgix.com/2015/10/13/next-generation-responsive-images-with-client.html
SmartCrop
https://github.com/jwagner/smartcrop.js/
Dragonļ¬‚y & reļ¬le
Dragonļ¬‚y & reļ¬le
ā€¢ tldr: we can fuss over implementation, but it is
mostly about architecture
Dragonļ¬‚y & reļ¬le
ā€¢ Rack middleware in your Rails app by default
ā€¢ performing on-the-ļ¬‚y image resize šŸ˜±
ā€¢ Rack standalone end point
ā€¢ Dragonļ¬‚y.app - upload, download, delete
ā€¢ Reļ¬le::App - upload, download, delete
ā€¢ Downloads are unthrottled
Dragonļ¬‚y & reļ¬le
ā€¢ BEFORE: Rails integrate with AWS
ā€¢ AFTER: Rails integrate with AWS + Rack app
ā€¢ Maintain identical AWS conļ¬g in both apps
ā€¢ Rails app couldnā€™t shed the ā€œconcernā€
ā€¢ Multiple images still require multiple models
reļ¬le
class Post < ActiveRecord::Base
has_many :images, dependent: :destroy
accepts_attachments_for :images, attachment: :file
end
class Image < ActiveRecord::Base
belongs_to :post
attachment :file
end
reļ¬le
class Post < ActiveRecord::Base
has_many :images, dependent: :destroy
accepts_attachments_for :images, attachment: :file
end
class Image < ActiveRecord::Base
belongs_to :post
attachment :file
end
ā€œNote it must be possible to persist images
given only the associated post and a ļ¬le. There
must not be any other validations or constraints
which prevent images from being savedā€
i.e. Must be pure dummy wrapper; no
validations here
reļ¬le download
https://github.com/reļ¬le/reļ¬le/blob/master/lib/reļ¬le/app.rb
get "/:token/:backend/:processor/:id/:filename" do
halt 404 unless download_allowed?
stream_file processor.call(file)
end
reļ¬le download
https://github.com/reļ¬le/reļ¬le/blob/master/lib/reļ¬le/app.rb
get "/:token/:backend/:processor/:id/:filename" do
halt 404 unless download_allowed?
stream_file processor.call(file)
end
How many ImageMagick can
you run in parallel?
has_many :images?
reļ¬le upload
https://github.com/reļ¬le/reļ¬le/blob/master/lib/reļ¬le/app.rb
post "/:backend" do
halt 404 unless upload_allowed?
tempfile = request.params.fetch("file").fetch(:tempfile)
file = backend.upload(tempfile)
content_type :json
{ id: file.id }.to_json
end
def file
file = backend.get(params[:id])
unless file.exists?
log_error("Could not find attachment by id: #{params[:id]}")
halt 404
end
file.download
end
post "/:backend" do
halt 404 unless upload_allowed?
tempfile = request.params.fetch("file").fetch(:tempfile)
file = backend.upload(tempfile)
content_type :json
{ id: file.id }.to_json
end
def file
file = backend.get(params[:id])
unless file.exists?
log_error("Could not find attachment by id: #{params[:id]}")
halt 404
end
file.download
end
reļ¬le upload
https://github.com/reļ¬le/reļ¬le/blob/master/lib/reļ¬le/app.rb
2 hops problem when
uploading and downloading
ā€¢ 3mb ļ¬le becomes 6mb each
way
ā€¢ #create and #show
becomes 12mb process
ā€¢ has_many :images?
reļ¬le
ā€¢ CarrierWave-styled named processors (e.g. :ļ¬ll, :thumb) vs
passing through syntax to underlying ImageMagick
ā€¢ personally prefer leveraging off existing knowledge
ā€¢ instead of manually conļ¬gured syntax sugar
ā€¢ ā€œ2 hop problemā€ however provide higher consistency
when running multiple reļ¬le servers
ā€¢ upload-here-download-there problem
ā€¢ (considering to perform 2-hop upload instead of async)
reļ¬le
ā€¢ Can upload to S3 direct and/or upload to reļ¬le
ā€¢ Redundancy interesting, but prefer less concern in Rails
app
ā€¢ Concept of cache and store to manage ā€œdangling ļ¬le
problemā€ is worth considering
ā€¢ Download urls are signed-only (this practice should be
adopted)
ā€¢ can partly counter motivation to abuse ā€œdangling ļ¬le
problemā€ (aka free ļ¬le hosting, whee!)
Questions?
Attache serverā€Ø
https://github.com/choonkeat/attache
Gem for Railsā€Ø
https://github.com/choonkeat/attache_rails
Demoā€Ø
https://attache-demo.herokuapp.com/

Weitere Ƥhnliche Inhalte

Was ist angesagt?

Code &amp; design your first website (3:16)
Code &amp; design your first website (3:16)Code &amp; design your first website (3:16)
Code &amp; design your first website (3:16)
Thinkful
Ā 
Designing your API Server for mobile apps
Designing your API Server for mobile appsDesigning your API Server for mobile apps
Designing your API Server for mobile apps
Mugunth Kumar
Ā 

Was ist angesagt? (20)

Code & Design your first website 4/18
Code & Design your first website 4/18Code & Design your first website 4/18
Code & Design your first website 4/18
Ā 
Code &amp; design your first website (3:16)
Code &amp; design your first website (3:16)Code &amp; design your first website (3:16)
Code &amp; design your first website (3:16)
Ā 
Designing your API Server for mobile apps
Designing your API Server for mobile appsDesigning your API Server for mobile apps
Designing your API Server for mobile apps
Ā 
Accessibility Hacks version 2
Accessibility Hacks version 2Accessibility Hacks version 2
Accessibility Hacks version 2
Ā 
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to DevelopmentWordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
Ā 
Things you should know about WordPress (but were always too afraid to ask): W...
Things you should know about WordPress (but were always too afraid to ask): W...Things you should know about WordPress (but were always too afraid to ask): W...
Things you should know about WordPress (but were always too afraid to ask): W...
Ā 
Front End page speed performance improvements for Drupal
Front End page speed performance improvements for DrupalFront End page speed performance improvements for Drupal
Front End page speed performance improvements for Drupal
Ā 
WordPress plugins
WordPress pluginsWordPress plugins
WordPress plugins
Ā 
Accessibility Hacks Wordcamp Manchester October 2018
Accessibility Hacks Wordcamp Manchester October 2018Accessibility Hacks Wordcamp Manchester October 2018
Accessibility Hacks Wordcamp Manchester October 2018
Ā 
JSLink for ITPros - SharePoint Saturday Jersey
JSLink for ITPros - SharePoint Saturday JerseyJSLink for ITPros - SharePoint Saturday Jersey
JSLink for ITPros - SharePoint Saturday Jersey
Ā 
Theming Wordpress with Adobe
Theming Wordpress with AdobeTheming Wordpress with Adobe
Theming Wordpress with Adobe
Ā 
WPD Training
WPD TrainingWPD Training
WPD Training
Ā 
Computer Science and Information Science 6th semester(2010 December) Questio...
 Computer Science and Information Science 6th semester(2010 December) Questio... Computer Science and Information Science 6th semester(2010 December) Questio...
Computer Science and Information Science 6th semester(2010 December) Questio...
Ā 
SUGUK Cambridge - Display Templates & JSLink for IT Pros
SUGUK Cambridge - Display Templates & JSLink for IT ProsSUGUK Cambridge - Display Templates & JSLink for IT Pros
SUGUK Cambridge - Display Templates & JSLink for IT Pros
Ā 
11 Amazing things I Learnt At Word Camp Sydney 2014
11 Amazing things I Learnt At Word Camp Sydney 201411 Amazing things I Learnt At Word Camp Sydney 2014
11 Amazing things I Learnt At Word Camp Sydney 2014
Ā 
Why & How to Create a WordPress Plugin
Why & How to Create a WordPress PluginWhy & How to Create a WordPress Plugin
Why & How to Create a WordPress Plugin
Ā 
jQuery Conference Austin Sept 2013
jQuery Conference Austin Sept 2013jQuery Conference Austin Sept 2013
jQuery Conference Austin Sept 2013
Ā 
Is Your (Client's) Website Ready for 2017?
Is Your (Client's) Website Ready for 2017?Is Your (Client's) Website Ready for 2017?
Is Your (Client's) Website Ready for 2017?
Ā 
jQuery Conference Boston 2011 CouchApps
jQuery Conference Boston 2011 CouchAppsjQuery Conference Boston 2011 CouchApps
jQuery Conference Boston 2011 CouchApps
Ā 
jQuery Chicago 2014 - Next-generation JavaScript Testing
jQuery Chicago 2014 - Next-generation JavaScript TestingjQuery Chicago 2014 - Next-generation JavaScript Testing
jQuery Chicago 2014 - Next-generation JavaScript Testing
Ā 

Andere mochten auch

Input Devices Maprang.
Input Devices Maprang.Input Devices Maprang.
Input Devices Maprang.
Maprang Rojanee
Ā 
How to upload a file
How to upload a fileHow to upload a file
How to upload a file
Tom Greenwell
Ā 
Key board interface
Key board interface Key board interface
Key board interface
sree deepika
Ā 
Barcode integration erp
Barcode integration   erpBarcode integration   erp
Barcode integration erp
madhappan
Ā 

Andere mochten auch (12)

Input Devices Maprang.
Input Devices Maprang.Input Devices Maprang.
Input Devices Maprang.
Ā 
How to upload a file
How to upload a fileHow to upload a file
How to upload a file
Ā 
Key board interface
Key board interface Key board interface
Key board interface
Ā 
FTP - File Transfer Protocol
FTP - File Transfer ProtocolFTP - File Transfer Protocol
FTP - File Transfer Protocol
Ā 
Barcode presentation 2013
Barcode presentation 2013Barcode presentation 2013
Barcode presentation 2013
Ā 
Barcode integration erp
Barcode integration   erpBarcode integration   erp
Barcode integration erp
Ā 
MicroService Architecture
MicroService ArchitectureMicroService Architecture
MicroService Architecture
Ā 
Bitrix24 crm
Bitrix24 crmBitrix24 crm
Bitrix24 crm
Ā 
Barcode technology
Barcode technologyBarcode technology
Barcode technology
Ā 
Developing applications with a microservice architecture (SVforum, microservi...
Developing applications with a microservice architecture (SVforum, microservi...Developing applications with a microservice architecture (SVforum, microservi...
Developing applications with a microservice architecture (SVforum, microservi...
Ā 
Introduction to EDI Basics
Introduction to EDI BasicsIntroduction to EDI Basics
Introduction to EDI Basics
Ā 
Bitrix24 crm review
Bitrix24 crm reviewBitrix24 crm review
Bitrix24 crm review
Ā 

Ƅhnlich wie File Upload 2015

The things we found in your website
The things we found in your websiteThe things we found in your website
The things we found in your website
hernanibf
Ā 
Word Press As A Cms
Word Press As A CmsWord Press As A Cms
Word Press As A Cms
Justin Sisley
Ā 
Web Development using Ruby on Rails
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on Rails
Avi Kedar
Ā 
Seven deadly theming sins
Seven deadly theming sinsSeven deadly theming sins
Seven deadly theming sins
George Stephanis
Ā 
Javascript Libraries
Javascript LibrariesJavascript Libraries
Javascript Libraries
elliando dias
Ā 

Ƅhnlich wie File Upload 2015 (20)

2015 rubyconf - ē™¾å¤§åŖ’é«”ē¶²ē«™å¾ž Wordpress 到 Rails ēš„大小äŗ‹
2015 rubyconf - ē™¾å¤§åŖ’é«”ē¶²ē«™å¾ž Wordpress 到 Rails ēš„大小äŗ‹2015 rubyconf - ē™¾å¤§åŖ’é«”ē¶²ē«™å¾ž Wordpress 到 Rails ēš„大小äŗ‹
2015 rubyconf - ē™¾å¤§åŖ’é«”ē¶²ē«™å¾ž Wordpress 到 Rails ēš„大小äŗ‹
Ā 
CSS3: Are you experienced?
CSS3: Are you experienced?CSS3: Are you experienced?
CSS3: Are you experienced?
Ā 
About Best friends - HTML, CSS and JS
About Best friends - HTML, CSS and JSAbout Best friends - HTML, CSS and JS
About Best friends - HTML, CSS and JS
Ā 
Practical tipsmakemobilefaster oscon2016
Practical tipsmakemobilefaster oscon2016Practical tipsmakemobilefaster oscon2016
Practical tipsmakemobilefaster oscon2016
Ā 
Grown-up javascript with AngularJS
Grown-up javascript with AngularJSGrown-up javascript with AngularJS
Grown-up javascript with AngularJS
Ā 
Deep dive on amazon rekognition architectures for image analysis - MCL318 - ...
Deep dive on amazon rekognition architectures for image analysis - MCL318  - ...Deep dive on amazon rekognition architectures for image analysis - MCL318  - ...
Deep dive on amazon rekognition architectures for image analysis - MCL318 - ...
Ā 
APIs for modern web apps
APIs for modern web appsAPIs for modern web apps
APIs for modern web apps
Ā 
The things we found in your website
The things we found in your websiteThe things we found in your website
The things we found in your website
Ā 
Riding the Edge with Ember.js
Riding the Edge with Ember.jsRiding the Edge with Ember.js
Riding the Edge with Ember.js
Ā 
Rich and Beautiful: Making Attractive Apps in HTML5 [Wpg 2013]
Rich and Beautiful: Making Attractive Apps in HTML5 [Wpg 2013]Rich and Beautiful: Making Attractive Apps in HTML5 [Wpg 2013]
Rich and Beautiful: Making Attractive Apps in HTML5 [Wpg 2013]
Ā 
Word Press As A Cms
Word Press As A CmsWord Press As A Cms
Word Press As A Cms
Ā 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
Ā 
Curtin University Frontend Web Development
Curtin University Frontend Web DevelopmentCurtin University Frontend Web Development
Curtin University Frontend Web Development
Ā 
Web Development using Ruby on Rails
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on Rails
Ā 
Seven deadly theming sins
Seven deadly theming sinsSeven deadly theming sins
Seven deadly theming sins
Ā 
Responsive Web Design: Clever Tips and Techniques
Responsive Web Design: Clever Tips and TechniquesResponsive Web Design: Clever Tips and Techniques
Responsive Web Design: Clever Tips and Techniques
Ā 
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
Ā 
Progressively Enhancing WordPress Themes
Progressively Enhancing WordPress ThemesProgressively Enhancing WordPress Themes
Progressively Enhancing WordPress Themes
Ā 
Making WordPress Your CMS and Automatically Updating a Self Hosted WordPress ...
Making WordPress Your CMS and Automatically Updating a Self Hosted WordPress ...Making WordPress Your CMS and Automatically Updating a Self Hosted WordPress ...
Making WordPress Your CMS and Automatically Updating a Self Hosted WordPress ...
Ā 
Javascript Libraries
Javascript LibrariesJavascript Libraries
Javascript Libraries
Ā 

KĆ¼rzlich hochgeladen

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
Ā 
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
Ā 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
Ā 
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
Ā 

KĆ¼rzlich hochgeladen (20)

Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Ā 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
Ā 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
Ā 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
Ā 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
Ā 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
Ā 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Ā 
tonesoftg
tonesoftgtonesoftg
tonesoftg
Ā 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
Ā 
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )šŸ” 9953056974šŸ”(=)/CALL GIRLS SERVICE
Ā 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
Ā 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
Ā 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
Ā 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
Ā 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
Ā 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
Ā 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
Ā 
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Ā 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
Ā 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
Ā 

File Upload 2015

  • 2. Howā€™s that predeļ¬ned styles doing for you? has_attached_file :asset, styles: { thumb: "100x100#" }
  • 3. Howā€™s that predeļ¬ned styles doing for you? has_attached_file :asset, styles: { thumb: "100x100#", medium: "320x>" }
  • 4. Howā€™s that predeļ¬ned styles doing for you? has_attached_file :asset, styles: { thumb: "100x100#", medium: "320x>", large: "1024x>" }
  • 5. Howā€™s that predeļ¬ned styles doing for you? has_attached_file :asset, styles: { thumb: "100x100#", medium: "320x>",ā€Ø big: "640x>", large: "1024x>" } Names starting to lose meaningā€¦
  • 6. Howā€™s that predeļ¬ned styles doing for you? has_attached_file :asset, styles: { thumb: "100x100#", thumb2x: "200x200#", medium: "320x>", medium2x: "640x>",ā€Ø big: "640x>", big2x: "1280x>", large: "1024x>", large2x: "2048x>" }
  • 7. Howā€™s that predeļ¬ned styles doing for you? has_attached_file :asset, styles: { thumb: "100x100#", thumb2x: "200x200#", medium: "320x>", medium2x: "640x>",ā€Ø big: "640x>", big2x: "1280x>", large: "1024x>", large2x: "2048x>" } Reprocess all the production ļ¬les, each time, we make changes. 404 while rake runs or do at midnight?
  • 9. Howā€™s that transformation juggling doing for you? class MyUploader < CarrierWave::Uploader::Base version :thumb do process resize_to_fill: [280, 280] end version :small_thumb, from_version: :thumb do process resize_to_fill: [20, 20] end end
  • 10. Howā€™s that transformation juggling doing for you? class MyUploader < CarrierWave::Uploader::Base version :thumb do process resize_to_fill: [280, 280] end version :small_thumb, from_version: :thumb do process resize_to_fill: [20, 20] end end Did your users wait in the foreground or background?
  • 11. Howā€™s that ļ¬le path conļ¬g doing for you?
  • 12. Howā€™s that ļ¬le path conļ¬g doing for you? class Avatar < ActiveRecord::Base has_attached_file :image,ā€Ø url: '/system/:class/:attachment/:id/:hash-:style.:extension', hash_secret: Rails.application.secrets.paperclip end
  • 13. Howā€™s that ļ¬le path conļ¬g doing for you? class Avatar < ActiveRecord::Base has_attached_file :image,ā€Ø url: '/system/:class/:attachment/:id/:hash-:style.:extension', hash_secret: Rails.application.secrets.paperclip end You sure this is the format? Or will they need to change?
  • 14. Howā€™s that ļ¬le path conļ¬g doing for you? class Avatar < ActiveRecord::Base has_attached_file :image,ā€Ø url: '/system/:class/:attachment/:id/:hash-:style.:extension', hash_secret: Rails.application.secrets.paperclip end
  • 15. Howā€™s that ļ¬le path conļ¬g doing for you? class Avatar < ActiveRecord::Base has_attached_file :image,ā€Ø url: '/system/:class/:attachment/:id/:hash-:style.:extension', hash_secret: Rails.application.secrets.paperclip end
  • 16. Howā€™s that ļ¬le path conļ¬g doing for you? CarrierWave.configure do |config| config.permissions = 0666 config.directory_permissions = 0777 config.storage = :file end
  • 17. Howā€™s that ļ¬le path conļ¬g doing for you? CarrierWave.configure do |config| config.permissions = 0666 config.directory_permissions = 0777 config.storage = :file end Did you conļ¬gure your MySQL data ļ¬le in your app too?
  • 18. Howā€™s that ļ¬le path conļ¬g doing for you? class Avatar < ActiveRecord::Base self.table = { name: "avatars", data: "/var/lib/mysql/data/avatars.MYD", index: "/var/lib/mysql/data/avatars.MYI" } end Did you conļ¬gure your MySQL data ļ¬le in your app too?
  • 19. Howā€™s that form validation error dance doing for you?
  • 20. Howā€™s that form validation error dance doing for you? ā€¢ User chooses a ļ¬le ā€¢ Submit & wait for ļ¬le to upload āŒ›ā€¦ ā€¢ Validation error: ā€œUsername is already taken!ā€ ā€¢ Re-render form
  • 21. Howā€™s that form validation error dance doing for you? ā€¢ User chooses a ļ¬le ā€¢ Submit & wait for ļ¬le to upload āŒ›ā€¦ ā€¢ Validation error: ā€œUsername is already taken!ā€ ā€¢ Re-render form Where dat ļ¬le go?
  • 22. Howā€™s that form validation error dance doing for you? http://stackoverļ¬‚ow.com/questions/5198602/not-losing-paperclip-attachment-when-model-cannot-be-saved-due-to-validation-err Closed: Wonā€™t Fix
  • 23. Howā€™s that form validation error dance doing for you? http://stackoverļ¬‚ow.com/questions/5198602/not-losing-paperclip-attachment-when-model-cannot-be-saved-due-to-validation-err
  • 24. Howā€™s that form validation error dance doing for you? http://stackoverļ¬‚ow.com/questions/5198602/not-losing-paperclip-attachment-when-model-cannot-be-saved-due-to-validation-err Answer: use CarrierWave
  • 25. Howā€™s that form validation error dance doing for you?
  • 26. Howā€™s that form validation error dance doing for you? ā€œIs there a standard approach? This seems like a very common use case.ā€
  • 27. Howā€™s the schema pollution doing for you?
  • 28. Howā€™s the schema pollution doing for you? class StoreMetadata < ActiveRecord::Migration def change add_column :users, :profile_image_filename, :string add_column :users, :profile_image_size, :integer add_column :users, :profile_image_content_type, :string end end
  • 29. Howā€™s the schema pollution doing for you? class StoreMetadata < ActiveRecord::Migration def change add_column :users, :profile_image_filename, :string add_column :users, :profile_image_size, :integer add_column :users, :profile_image_content_type, :string end end
  • 30. Howā€™s that multiple ļ¬les doing for you?
  • 31. Howā€™s that multiple ļ¬les doing for you? class Post < ActiveRecord::Base has_many :images, dependent: :destroy end
  • 32. Howā€™s that multiple ļ¬les doing for you? class Post < ActiveRecord::Base has_many :images, dependent: :destroy end class Image < ActiveRecord::Base belongs_to :post attachment :file end
  • 33. Howā€™s that multiple ļ¬les doing for you? class Post < ActiveRecord::Base has_many :images, dependent: :destroy end class Image < ActiveRecord::Base belongs_to :post attachment :file end
  • 34. Howā€™s that multiple ļ¬les doing for you? class Post < ActiveRecord::Base has_many :images, dependent: :destroy end class Image < ActiveRecord::Base belongs_to :post attachment :file end Is this what you want or just what youā€™re accustomed to?
  • 35. Howā€™s Amazon Lambda doing for you? ā€¢ User chooses a ļ¬le ā€¢ Submit & wait for ļ¬le to upload āŒ›ā€¦ ā€¢ Success! ā€¢ Render page with thumbnailā€¦ How many thumbnails - 404?
  • 36. Howā€™s Amazon Lambda doing for you? ā€¢ User chooses a ļ¬le ā€¢ Submit & wait for ļ¬le to upload āŒ›ā€¦ ā€¢ Success! ā€¢ Render page with thumbnailā€¦ Direct upload to AWS? Cancel form submit - delete ļ¬les & thumbnails? Deep integration & assumption
  • 37. Howā€™s Dragonļ¬‚y doing for you? http://markevans.github.io/dragonļ¬‚y/
  • 38. Howā€™s reļ¬le doing for you? https://github.com/reļ¬le/reļ¬le
  • 40. Take a step back
  • 41. Take a step back ā€¢ We want to store a bunch of attributes in a model ā€¢ e.g. Title, Body, Tags, Photoā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø
  • 42. Take a step back {photo} {title} {body}
  • 43. Take a step back <img src={photo}> <h1>{title}</h1> {body}
  • 44. Take a step back ā€¢ Why should photo be a disproportionately complicated attribute in my Article model? ā€¢ stored ļ¬le path ā€¢ conversion ā€¢ background job ā€¢ aws conļ¬g ā€¢ clean up on delete
  • 45. Take a step back ā€¢ Why should photo be a disproportionately complicated attribute in my Article model? ā€¢ stored ļ¬le path ā€¢ conversion ā€¢ background job ā€¢ validation error dance ā€¢ aws conļ¬g
  • 46. Take a step back ā€¢ Frankly photo_url is best; least intrusiveā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø
  • 47. Take a step back ā€¢ Frankly photo_url is best; least intrusive ā€¢ Problems ā€¢ Remote url 404? (not exclusive to your app) ā€¢ Asking users to give us a URL is a hard sell ā€¢ Need to render other sizes ā€¢ Filter by meta data
  • 48. Take a step back ā€¢ Frankly photo_url is best; least intrusive ā€¢ Problems ā€¢ Remote url 404? (not exclusive to your app) ā€¢ Asking users to give us a URL is a hard sell ā€¢ Need to render other sizes ā€¢ Filter by meta data
  • 49. Take a step back ā€¢ Frankly photo_url is best; least intrusive ā€¢ Problems ā€¢ Remote url 404? (not exclusive to your app) ā€¢ Asking users to give us a URL is a hard sell ā€¢ Need to render other sizes ā€¢ Filter by meta data
  • 50. Take a step back ā€¢ Frankly photo_url is best; least intrusive ā€¢ Solutions ā€¢ Exclusive server for your app ā€¢ Upload to that server ā€¢ On-the-ļ¬‚y resize based on URL ā€¢ Store url with meta data: photo_json instead?
  • 52. ā€¢ PostgreSQL, MySQL ā€¢ Redis ā€¢ Memcached ā€¢ SMTP server (Mail)ā€Ø ā€Ø ā€Ø ā€Ø You are already Generic server to do specialised work Not speciļ¬c to your business logic
  • 53. ā€¢ Not a new pattern ā€¢ Mostly commercial servicesā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€¢ Maybe it has to be Free & Open Source to become a default pattern Image server
  • 54. Want ā€¢ Move the ā€œconcernā€ out of my app ā€¢ photo is a regular attribute ā€¢ conļ¬gure my app & forget it existā€Ø ā€Ø ā€Ø ā€Ø
  • 55. Want ā€¢ Move the ā€œconcernā€ out of my app ā€¢ photo is a regular attribute ā€¢ conļ¬gure my app & forget it existā€Ø ā€Ø ā€Ø ā€Ø What would my app look like in a better world?
  • 56. My app: Bare minimum create_table "users" do |t| t.string "name" t.json "avatar" t.json "photos" end
  • 57. My app: Bare minimum create_table "users" do |t| t.string "name" t.json "avatar" t.json "photos" # multiple files in a column end
  • 58. My app: Bare minimum Image serverRails appBrowser { avatar: #<File..> }
  • 59. My app: Bare minimum Image serverRails appBrowser { avatar: #<File..> } {ā€œpathā€:ā€œx.jpgā€, ā€œgeometryā€:ā€œ200x600ā€} #<File..>
  • 60. My app: Bare minimum Image serverRails appBrowser {ā€œpathā€:ā€œx.jpgā€, ā€œgeometryā€:ā€œ200x600ā€} #<File..> user.avatar={ā€œpathā€: ā€œx.jpgā€ā€¦} user.save <img src=ā€œx.jpgā€> { avatar: #<File..> }
  • 61. My app: Bare minimum Image serverRails appBrowser {ā€œpathā€:ā€œx.jpgā€, ā€œgeometryā€:ā€œ200x600ā€} <img src=ā€œx.jpgā€> #<File..> GET x.jpg #<File..> user.avatar={ā€œpathā€: ā€œx.jpgā€ā€¦} user.save { avatar: #<File..> }
  • 62. My app: Bare minimum ā€¢ Browser render <file> ļ¬eld; regular form submit ā€¢ Receive binary param, uploads to attache server and stores the json response instead ā€¢ Your app render <img src> requesting for image in certain size, e.g. http://example/200x/ file.pngā€Ø ā€Ø ā€Ø
  • 65. { avatar: {ā€œpathā€:ā€œx.jpgā€, ā€¦ } Image serverRails appBrowser #<File..> {ā€œpathā€:ā€œx.jpgā€, ā€œgeometryā€:ā€œ200x600ā€} user.avatar={ā€œpathā€: ā€œx.jpgā€ā€¦} user.save <img src=ā€œx.jpgā€> Progressive Enhancement
  • 66. ā€¢ Browser render <file> ļ¬eld; regular form submit ā€¢ Receive binary param, uploads to attache server and stores the json response instead ā€¢ Your app render <img src> requesting for image in certain size, e.g. http://example/200x/ file.pngā€Ø ā€Ø ā€Ø Progressive Enhancement
  • 67. ā€¢ Browser render <file> ļ¬eld; regular form submit ā€¢ Receive binary param, uploads to attache server and stores the json response instead ā€¢ Your app render <img src> requesting for image in certain size, e.g. http://example/200x/ file.pngā€Ø ā€Ø ā€Ø ā€¢ JS upload directly to attache server; ā€œDirect uploadā€ in AWS parlance ā€¢ No binary in params; receive and store json attribute Progressive Enhancement ā€¢ When after_update & after_destroy removes obsolete ļ¬le from attache via delete API
  • 68. ā€¢ Just use Ruby; just use your framework ā€¢ Pre-render multiple sizes ā€¢ fetch the urls, server will generate and cache ā€¢ Validation ā€¢ validating a regular json attribute How do Iā€¦
  • 69. ā€¢ Move the ā€œconcernā€ out of my app ā€¢ photo is a regular attribute ā€¢ conļ¬gure my app & forget it existā€Ø ā€Ø ā€Ø ā€Ø Want (contā€™d)
  • 70. Want (contā€™d) ā€¢ Move the ā€œconcernā€ out of my app ā€¢ photo is a regular attribute ā€¢ conļ¬gure my app & forget it exist ā€¢ Separate, standalone server ā€¢ Minimal / zero ongoing administration
  • 71. Want (contā€™d) ā€¢ Move the ā€œconcernā€ out of my app ā€¢ photo is a regular attribute ā€¢ conļ¬gure my app & forget it exist ā€¢ Separate, standalone server ā€¢ Minimal / zero ongoing administration How does this server work?
  • 72. Attache File Server ā€¢ HTTP server with simple APIs ā€¢ upload ā€¢ download ā€¢ delete ā€¢ Rack app + ImageMagick ā€¢ Go? Node? C++? PHP? ā€¢ GraphicsMagick? MyResizer.bash?
  • 73. ā€¢ Uploaded ļ¬les are stored locally ā€¢ Resize local ļ¬le on-the-ļ¬‚y ā€¢ conļ¬gurable pool size to limit concurrent resizing ā€¢ Sync upload to cloud storage ā€¢ 2 hop problem vs complexity ā€¢ Fixed local storage, purge LRU (zero maintenance) ā€¢ Spin up new fresh servers anytimeā€¦ ā€Ø Attache File Server
  • 74. ā€¢ When requested ļ¬le does not exist locally ā€¢ fetch from cloud storage & write locally ā€¢ resume operationsā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø Attache File Server
  • 75. ā€¢ Remove obsolete ļ¬le is ā€œbest effortā€ ā€¢ If photo delete failed, do you Error 500 or stop the world?ā€Ø ā€Ø ā€Ø ā€Ø ā€¢ OCDs can schedule rake task remove dangling ļ¬les? Attache File Server
  • 76. ā€¢ Caching in production ā€¢ Browser ā†’ CDN ā†’ Varnish ā†’ Disk ā†’ Cloudā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø ā€Ø Attache File Server
  • 79. tus.io ā€¢ Open protocol for resumable uploads built on HTTP ā€¢ Perfect for mobile apps ā€¢ Rack middleware implemented in choonkeat/ attache#10
  • 80. Responsive Images with Client Hints http://blog.imgix.com/2015/10/13/next-generation-responsive-images-with-client.html
  • 83. Dragonļ¬‚y & reļ¬le ā€¢ tldr: we can fuss over implementation, but it is mostly about architecture
  • 84. Dragonļ¬‚y & reļ¬le ā€¢ Rack middleware in your Rails app by default ā€¢ performing on-the-ļ¬‚y image resize šŸ˜± ā€¢ Rack standalone end point ā€¢ Dragonļ¬‚y.app - upload, download, delete ā€¢ Reļ¬le::App - upload, download, delete ā€¢ Downloads are unthrottled
  • 85. Dragonļ¬‚y & reļ¬le ā€¢ BEFORE: Rails integrate with AWS ā€¢ AFTER: Rails integrate with AWS + Rack app ā€¢ Maintain identical AWS conļ¬g in both apps ā€¢ Rails app couldnā€™t shed the ā€œconcernā€ ā€¢ Multiple images still require multiple models
  • 86. reļ¬le class Post < ActiveRecord::Base has_many :images, dependent: :destroy accepts_attachments_for :images, attachment: :file end class Image < ActiveRecord::Base belongs_to :post attachment :file end
  • 87. reļ¬le class Post < ActiveRecord::Base has_many :images, dependent: :destroy accepts_attachments_for :images, attachment: :file end class Image < ActiveRecord::Base belongs_to :post attachment :file end ā€œNote it must be possible to persist images given only the associated post and a ļ¬le. There must not be any other validations or constraints which prevent images from being savedā€ i.e. Must be pure dummy wrapper; no validations here
  • 89. reļ¬le download https://github.com/reļ¬le/reļ¬le/blob/master/lib/reļ¬le/app.rb get "/:token/:backend/:processor/:id/:filename" do halt 404 unless download_allowed? stream_file processor.call(file) end How many ImageMagick can you run in parallel? has_many :images?
  • 90. reļ¬le upload https://github.com/reļ¬le/reļ¬le/blob/master/lib/reļ¬le/app.rb post "/:backend" do halt 404 unless upload_allowed? tempfile = request.params.fetch("file").fetch(:tempfile) file = backend.upload(tempfile) content_type :json { id: file.id }.to_json end def file file = backend.get(params[:id]) unless file.exists? log_error("Could not find attachment by id: #{params[:id]}") halt 404 end file.download end
  • 91. post "/:backend" do halt 404 unless upload_allowed? tempfile = request.params.fetch("file").fetch(:tempfile) file = backend.upload(tempfile) content_type :json { id: file.id }.to_json end def file file = backend.get(params[:id]) unless file.exists? log_error("Could not find attachment by id: #{params[:id]}") halt 404 end file.download end reļ¬le upload https://github.com/reļ¬le/reļ¬le/blob/master/lib/reļ¬le/app.rb 2 hops problem when uploading and downloading ā€¢ 3mb ļ¬le becomes 6mb each way ā€¢ #create and #show becomes 12mb process ā€¢ has_many :images?
  • 92. reļ¬le ā€¢ CarrierWave-styled named processors (e.g. :ļ¬ll, :thumb) vs passing through syntax to underlying ImageMagick ā€¢ personally prefer leveraging off existing knowledge ā€¢ instead of manually conļ¬gured syntax sugar ā€¢ ā€œ2 hop problemā€ however provide higher consistency when running multiple reļ¬le servers ā€¢ upload-here-download-there problem ā€¢ (considering to perform 2-hop upload instead of async)
  • 93. reļ¬le ā€¢ Can upload to S3 direct and/or upload to reļ¬le ā€¢ Redundancy interesting, but prefer less concern in Rails app ā€¢ Concept of cache and store to manage ā€œdangling ļ¬le problemā€ is worth considering ā€¢ Download urls are signed-only (this practice should be adopted) ā€¢ can partly counter motivation to abuse ā€œdangling ļ¬le problemā€ (aka free ļ¬le hosting, whee!)
  • 94. Questions? Attache serverā€Ø https://github.com/choonkeat/attache Gem for Railsā€Ø https://github.com/choonkeat/attache_rails Demoā€Ø https://attache-demo.herokuapp.com/