2015-12-11 26 views
13

Sto usando dropzone con S3 e carrierwave. Sono in grado di caricare immagini tramite Google Chrome, ma non riesco a farlo funzionare con Safari, il che è strano.Rails: caricamento di dropzone, S3, carrierwave, non funziona in Safari, ma funziona su Google Chrome

Questa è la mia forma

= nested_form_for @trip, html: { multipart: true, id: 'fileupload', class: 'directUpload', data: { 'form-data' => (@s3_direct_post.fields), 'url' => @s3_direct_post.url, 'host' => URI.parse(@s3_direct_post.url).host } } do |f| 
    .dropzone#imageUpload 
    = f.simple_fields_for :trip_images, TripImage.new, child_index: TripImage.new.object_id do |ff| 
    = ff.file_field :photo, class: 'hide form-fields' 
    = f.button :submit, id: "submit-data" 

Questo è nel controller di viaggio

def set_s3_direct_post 
    @s3_direct_post = S3_BUCKET.presigned_post(key: "/uploads/temporary/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public-read', content_type: 'image/jpeg') 
end 

Questo è il modello TripImage

class TripImage < ActiveRecord::Base 
    belongs_to :resource, :polymorphic => true 
    mount_uploader :photo, PhotoUploader 
    after_create :process_async 

    def to_jq_upload 
    { 
     'name' => read_attribute(:attachment_file_name), 
     'size' => read_attribute(:attachment_file_size), 
     'url' => attachment.url(:original), 
     'thumbnail_url' => attachment.url(:thumb), 
     'delete_url' => "/photos/#{id}", 
     'delete_type' => 'DELETE' 
    } 
    end 

    private 

    def process_async 
    PhotoVersioningJob.set(wait: 5.seconds).perform_later(self.id) 
    end 

end 

Questo è js

$(function(){ 
    $('.directUpload').find(".dropzone").each(function(i, elem) { 
    s3ImageUpload(elem); 
    }); 
}) 

function s3ImageUpload(elem){ 
    var fileInput = $(elem); 
    var form   = $(fileInput.parents('form:first')); 
    var form_url = form.data('url'); 
    var form_data = form.data('form-data'); 
    Dropzone.options.imageUpload = { 
    url: form_url, 
    params: form_data, 
    uploadMultiple: false, 
    addRemoveLinks: true, 
    removedfile: function(file){ 
     //some codes 
    }, 
    success: function(file, serverResponse, event){ 
     //some codes 
    }, 
    error: function(data){ 
     //some codes 
    } 
    }; 
} 

EDIT: configurazione attuale CORS

<?xml version="1.0" encoding="UTF-8"?> 
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
    <CORSRule> 
     <AllowedOrigin>*.example.com</AllowedOrigin> 
     <AllowedMethod>GET</AllowedMethod> 
     <AllowedMethod>POST</AllowedMethod> 
     <AllowedMethod>PUT</AllowedMethod> 
     <MaxAgeSeconds>3000</MaxAgeSeconds> 
     <AllowedHeader>*</AllowedHeader> 
     <AllowedHeader>origin</AllowedHeader> 
    </CORSRule> 
</CORSConfiguration> 

Testato e non funziona

EDIT: Ho anche S3 upload diretto, non so se questo incide anche tu?

S3DirectUpload.config do |c| 
    c.access_key_id = Rails::AWS.config['access_key_id']  # your access key id 
    c.secret_access_key = Rails::AWS.config['secret_access_key'] # your secret access key 
    c.bucket = Rails::AWS.config['bucket_name']    # your bucket name 
    c.region = 's3'    # region prefix of your bucket url. This is _required_ for the non-default AWS region, eg. "s3-eu-west-1" 
end 
+0

non ho accesso ai safari ma immagino che le righe sopra la richiesta potrebbero contenere chiamate non supportate da Safari. Quali dati contiene ciascuna variabile fileInput, form, form_url e form_data? –

+0

Anche quali dati contengono queste variabili quando si utilizza chrome? –

+0

Come funziona in Safari? Vedi eventuali errori nella console? – vemv

risposta

6

ho incontrato un problema simile con Safari di recente, e ha scoperto che si sta inviando un extra Access-Control-request-header che Chrome non lo fa - in particolare 'origine'. Per risolvere questa differenza, avevo bisogno di aggiornare la mia configurazione di AWS CORS nel bucket di destinazione.

AWS Documentation on the necessity of request headers matching an allowed header config. Il terzo punto elenco rende esplicito questo requisito:

Ogni intestazione elencata nell'intestazione di Access-Control-Request-Headers della richiesta sulla richiesta di preflight deve corrispondere a un elemento AllowedHeader.

This helpful StackOverflow answer dà un esempio di configurazione:

<?xml version="1.0" encoding="UTF-8"?> 
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
    <CORSRule> 
    <AllowedOrigin>*</AllowedOrigin> 
    <AllowedMethod>GET</AllowedMethod> 
    <MaxAgeSeconds>3000</MaxAgeSeconds> 
    <AllowedHeader>Authorization</AllowedHeader> 
    <AllowedHeader>x-requested-with</AllowedHeader> 
    </CORSRule> 
</CORSConfiguration> 

E quello che doveva essere aggiunto per farlo funzionare in Safari:

<AllowedHeader>origin</AllowedHeader> 
+0

Speravo che potesse fare il trucco. Ho aggiornato la mia domanda per mostrare quale sia la mia configurazione CORS. È questo che dovrebbe essere? – hellomello

+0

Inoltre, non sono sicuro se il problema CORS? Sto guardando i log di heroku e non INSERISCE NELLA banca dati. Questo succede in Chrome però. – hellomello

+0

@hellomello si, supponendo che * .example.com sia il nome host del tuo sito web in realtà. Inoltre, dovrai assicurarti di non ottenere una versione cache della risposta pre-volo che nel tuo caso resterà attiva per un massimo di 3000 secondi. Se non funziona ancora per te, posso solo pensare a un altro problema che stavamo provando a chiamare un URL https da una pagina http o viceversa. Non sono un esperto nello stack che stai utilizzando, ma ho un bel po 'di esperienza con i caricamenti diretti di s3. L'unica ragione per cui ho fatto questa risposta è che si presentava esattamente allo stesso modo (non funziona solo in safari) – craigts