rails images aws ruby-on-rails amazon-s3 carrierwave

ruby on rails - images - Subida programática de Carrierwave



rails image upload (2)

De acuerdo, tengo una solución de trabajo. Voy a explicar mejor lo que hice para que otros puedan aprender de mi experiencia. Aquí va:

Suponiendo que tienes una aplicación para iPhone que toma una foto:

//handle the image that has just been selected - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { //get the image UIImage* image = [info valueForKey:@"UIImagePickerControllerOriginalImage"]; //scale and rotate so you''re not sending a sideways image -> method provided by http://blog.logichigh.com/2008/06/05/uiimage-fix/ image = [self scaleAndRotateImage:image]; //obtain the jpeg data (.1 is quicker to send, i found it better for testing) NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, .1)]; //get the data into a string NSString* imageString = [NSString stringWithFormat:@"%@", imageData]; //remove whitespace from the string imageString = [imageString stringByReplacingOccurrencesOfString:@" " withString:@""]; //remove < and > from string imageString = [imageString substringWithRange:NSMakeRange(1, [imageString length]-2)]; self.view.hidden = YES; //dismissed the camera [picker dismissModalViewControllerAnimated:YES]; //posts the image [self performSelectorInBackground:@selector(postImage:) withObject:imageString]; } - (void)postImage:(NSString*)imageData { //image string formatted in json NSString* imageString = [NSString stringWithFormat:@"{/"image/": /"%@/", /"authenticity_token/": /"/", /"utf8/": /"✓/"}", imageData]; //encoded json string NSData* data = [imageString dataUsingEncoding:NSUTF8StringEncoding]; //post the image [API postImage:data]; }[/code] Then for the post: [code]+(NSArray*)postImage:(NSData*) data { //url that you''re going to send the image to NSString* url = @"www.yoururl.com/images"; //pretty self explanatory request building NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]]; [request setTimeoutInterval:10000]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPMethod: @"POST"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setHTTPBody:data]; NSError *requestError; NSURLResponse *urlResponse = nil; NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError]; return [API generateArrayWithData:result]; }

En el lado de los rieles, establecí un método específico para manejar imágenes móviles, esto debería ayudarlo a publicar la imagen en su cuenta de Amazon S3 a través de Carrierwave:

def post respond_to do |format| format.json { #create a new image so that you can call it''s class method (a bit hacky, i know) @image = Image.new #get the json image data pixels = params[:image] #convert it from hex to binary pixels = @image.hex_to_string(pixels) #create it as a file data = StringIO.new(pixels) #set file types data.class.class_eval { attr_accessor :original_filename, :content_type } data.original_filename = "test1.jpeg" data.content_type = "image/jpeg" #set the image id, had some weird behavior when i didn''t @image.id = Image.count + 1 #upload the data to Amazon S3 @image.upload(data) #save the image if @image.save! render :nothing => true end } end end

Esto funciona para mí para publicar y creo que debería ser bastante ampliable. Para los métodos de clase:

#stores the file def upload(file) self.path.store!(file) end #converts the data from hex to a string -> found code here http://4thmouse.com/index.php/2008/02/18/converting-hex-to-binary-in-4-languages/ def hex_to_string(hex) temp = hex.gsub("/s", ""); ret = [] (0...temp.size()/2).each{|index| ret[index] = [temp[index*2, 2]].pack("H2")} file = String.new ret.each { |x| file << x} file end

No digo que este código sea perfecto, ni siquiera por un disparo largo. Sin embargo, funciona para mí. Estoy abierto a sugerencias si alguien piensa que podría mejorarse. ¡Espero que esto ayude!

En este momento, en mi aplicación Rails, estoy usando Carrierwave para subir archivos a Amazon S3. Estoy usando un selector de archivos y un formulario para seleccionar y enviar el archivo, esto funciona bien.

Sin embargo, ahora intento hacer publicaciones desde una aplicación de iPhone y recibo el contenido del archivo. Me gustaría crear un archivo usando estos datos y luego subirlo usando Carrierwave para poder recuperar la ruta correcta.

El modelo de archivo de mayo consiste en:

path file_name id user_id

donde la ruta es la url de Amazon S3. Me gustaría hacer algo como esto para construir los archivos:

data = params[:data] ~file creation magic using data~ ~carrierwave upload magic using file~ @user_id = params[:id] @file_name = params[:name] @path = path_provided_by_carrierwave_magic File.build(@user_id, @file_name, @path)

Realmente amaría a alguien que me señale en la dirección correcta. ¡Gracias!


Esto es lo que escribí para realizar una carga en s3 desde una aplicación ios a través de carrierwave:

Primero el modelo de Foto

class Photo include Mongoid::Document include Mongoid::Timestamps mount_uploader :image, PhotoImageUploader field :title, :type => String field :description, :type => String end

Segundo en el Api :: V1 :: PhotosController

def create @photo = current_user.photos.build(params) if @photo.save render :json => @photo.to_json, :status=>201 else render :json => {:errors => @photo.errors}.to_json, :status=>403 end end

Entonces la llamada desde mi aplicación de iPhone usando AFNetworking

-(void) sendNewPhoto { NSURL *url = [NSURL URLWithString:@"http://myserverurl.com"]; NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:_photoTitle.text, @"title", _photoDescription.text, @"description",nil]; AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; NSString *endUrl = [NSString stringWithFormat:@"/api/v1/photos?auth_token=%@", [[User sharedInstance] token]]; NSData *imageData = UIImageJPEGRepresentation(_photo.image, 1.0); NSURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:endUrl parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [formData appendPartWithFileData:imageData name:@"image" fileName:@"image.jpg" mimeType:@"image/jpg"]; }]; AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { NSLog(@"%@", JSON); } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { NSLog(@"Error creating photo!"); NSLog(@"%@", error); }]; [operation start]; }

En la respuesta JSON puedo obtener la nueva instancia de Foto con el atributo image.url establecido en la url en el s3.