2013-08-29 14 views
25

Ich habe eine Foto-Upload-Funktion in meiner Rails App. Die App lädt direkt über smar3 und carrierwave über smarag und dog auf s3 hoch. Das Problem, das ich habe, ist, wenn ein Foto per Handy über die Option "Foto aufnehmen" im Hochformat hochgeladen wird (beachten Sie, dass dies mit dem iPhone ist, aber ich glaube, Android hat das gleiche Problem). Nach dem Hochladen erscheint das Bild auf Mobilgeräten einwandfrei, wenn es jedoch auf dem Desktop angezeigt wird, erscheint das Bild um 90 Grad gedreht.Exif Bilddrehung Problem mit Carrierwave und rmagick zum Hochladen auf s3

Durch meine Forschung scheint es ein Problem mit Exif. Diese stackoverflow responder skizziert 2 mögliche Lösungen. Diese gist sieht auch vielversprechend aus.

Bis jetzt habe ich ein paar Lösungen gefunden, aber keine haben funktioniert. Idealerweise möchte ich, dass das Foto als Porträt auf s3 gespeichert wird, und dann das Bild einfach so anzeigen, wie es ist.

Alle Vorschläge werden sehr geschätzt.

Unten ist mein Code

app/uploaders/image_uploader.rb

class ImageUploader < CarrierWave::Uploader::Base 
    include CarrierWaveDirect::Uploader 

    include CarrierWave::RMagick 

    # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: 
    include Sprockets::Helpers::RailsHelper 
    include Sprockets::Helpers::IsolatedHelper 

    include CarrierWave::MimeTypes 
    process :fix_exif_rotation 
    process :set_content_type 


    version :thumb do 
    process resize_to_fill: [200, 200] 
    end 

    def extension_white_list 
    %w(jpg jpeg png) 
    end 


    def fix_exif_rotation #this is my attempted solution 
    manipulate! do |img| 
     img = img.auto_orient! 
    end 
    end 


end 

app/models/s3_image.rb

class S3Image < ActiveRecord::Base 
    attr_accessible :image, :name, :user_id 
    mount_uploader :image, ImageUploader 

    belongs_to :user 


    def image_name 
    File.basename(image.path || image.filename) if image 
    end 


    class ImageWorker 
    include Sidekiq::Worker 

    def perform(id, key) 
     s3_image = S3Image.find(id) 
     s3_image.key = key 
     s3_image.remote_image_url = s3_image.image.direct_fog_url(with_path: true) 
     s3_image.save! 
     s3_image.update_column(:image_processed, true) 
    end 
    end 
end 

config/initializers/carrierwave.rb

CarrierWave.configure do |config| 
    config.fog_credentials = { 
    provider: "AWS", 
    aws_access_key_id: " ... ", 
    aws_secret_access_key: " ... " 
    } 
    config.fog_directory = " ... " 
end 

BTW ich verwendet diese Railscast als Leitfaden für die Einrichtung meiner s3-Upload.

Antwort

31

Nun, ich habe das funktioniert mit Nebel statt oder carrierwave_direct.

Unten ist der Code, der für mich am Ende arbeiten:

app/uploaders/image_uploader.rb

class ImageUploader < CarrierWave::Uploader::Base 
    include CarrierWave::MiniMagick 

    include Sprockets::Helpers::RailsHelper 
    include Sprockets::Helpers::IsolatedHelper 

    storage :fog 

    # Override the directory where uploaded files will be stored. 
    # This is a sensible default for uploaders that are meant to be mounted: 
    def store_dir 
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 
    end 


    def fix_exif_rotation #this is my attempted solution 
    manipulate! do |img| 
     img.tap(&:auto_orient) 
    end 
    end 

    process :fix_exif_rotation 
end 

app/models/s3_image.rb

class S3Image < ActiveRecord::Base 
    attr_accessible :image, :name, :user_id, :image_cache 
    mount_uploader :image, ImageUploader 

    belongs_to :user 
end 

initializers/carrierwave .rb

CarrierWave.configure do |config| 
    config.fog_credentials = { 
    provider: "AWS", 
    aws_access_key_id: " ... ", 
    aws_secret_access_key: " ... ", 
    region: 'us-west-2' 
    } 
    config.fog_directory = " ... " 
end 
+0

Warum der 'tap'?() –

+0

Ich bin mir nicht sicher ... – lando2319

+11

@ JonathanAllard der 'manipulate!' Block will ein Bild, aber 'image.auto_orient' gibt einen leeren String zurück. 'image.tap (&: auto_orient)' entspricht ungefähr image.auto_orient; Bild'. – benizi

14

Ich hatte ein ähnliches Problem und behob es mit einem Ansatz fast identisch mit Ihrem.

# In the uploader: 
def auto_orient 
    manipulate! do |img| 
    img = img.auto_orient 
    end 
end 

(Beachten Sie, dass ich nicht auto_orient! nenne -. Nur auto_orient, ohne Knall)

Dann habe ich process :auto_orient als die erste Zeile jeder version ich erstellen. Zum Beispiel:

version :square do 
    process :auto_orient 
    process :resize_to_fill => [600, 600] 
end 
+0

Vielen Dank für den Vorschlag, leider hat dies mein Problem nicht behoben. – lando2319

+0

Ich habe das zu meinen Versionen hinzugefügt, dann habe ich die Versionen neu erstellt und die Probleme mit Seitwärtsbildern behoben. Bis jetzt habe ich es nur mit Bildern getestet, die über Safari auf ios 7 hochgeladen wurden. Hoffentlich funktioniert es auf der ganzen Linie. Vielen Dank. – wuliwong

+0

Danke, Sumeet, funktioniert super! – littleforest

4

Meine Lösung (ganz ähnlich wie Sumeet):

# painting_uploader.rb 
process :right_orientation 
def right_orientation 
    manipulate! do |img| 
    img.auto_orient 
    img 
    end 
end 

Es ist wirklich wichtig, ein Bild zurückzugeben.Andernfalls werden Sie ein

NoMethodError (undefined method `write' for "":String): 
+3

Ihre Lösung funktionierte für mich, während @ Sumeet nicht, obwohl ähnlich. Danke auch für den Tipp über die Notwendigkeit, * ein Bild * zurückzugeben. Für den Datensatz hatte ich einen ähnlichen Fehler 'NoMethodError (undefinierte Methode 'destroy!' Für" ": String)'. – user664833

1

Lando2319's answer bekommen nicht für mich arbeiten.

Ich verwende RMagick.

ich es geschafft machen ImageMagick die richtige Ausrichtung gelten (und die EXIF-Rotationsdaten zurückzusetzen, um eine doppelte Drehung durch den Betrachter zu vermeiden) unter Verwendung von:

def fix_exif_rotation # put this before any other process in the Carrierwave uploader 

manipulate! do |img| 
    img.tap(&:auto_orient!) 
end 

Der Unterschied zwischen meiner Lösung & Landos ist der Knall (!). In meinem Fall war es absolut notwendig.