【问题标题】:Carrierwave Programatic UploadCarrierwave 程序化上传
【发布时间】:2012-09-15 00:16:19
【问题描述】:

现在在我的 Rails 应用程序中,我正在使用 Carrierwave 将文件上传到 Amazon S3。我正在使用文件选择器和表单来选择和提交文件,这很好用。

但是,我现在正尝试从 iPhone 应用程序发布帖子,并且正在接收文件的内容。我想使用这些数据创建一个文件,然后使用 Carrierwave 上传它,这样我就可以获得正确的路径。

可能文件模型包括:

path
file_name
id
user_id

其中 path 是 Amazon S3 url。我想做这样的事情来构建文件:

 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)

真的很想有人指出我正确的方向。谢谢!

【问题讨论】:

    标签: ruby-on-rails amazon-s3 carrierwave


    【解决方案1】:

    好的,我有一个可行的解决方案。我将最好地解释我的所作所为,以便其他人可以从我的经验中学习。如下:

    假设您有一个可以拍照的 iPhone 应用:

    //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];
    }
    

    在rails方面我设置了一个专门用于处理移动图像的方法,这应该可以帮助您通过Carrierwave将图像发布到您的Amazon S3帐户:

    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
    

    这对我来说很适合发帖,我觉得应该可以扩展。对于类方法:

    #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
    

    并不是说这段代码是完美的,甚至不是很远。但是,它确实对我有用。如果有人认为可以改进,我愿意接受建议。希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      这是我写的通过carrierwave从ios应用程序上传到s3的内容:

      首先是照片模型

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

      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
      

      然后我的 iPhone 应用程序使用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];
      }
      

      在 JSON 响应中,我可以获取 Photo 的新实例,其中 image.url 属性设置为 s3 中的 url。

      【讨论】:

        猜你喜欢
        • 2012-02-19
        • 1970-01-01
        • 2015-11-29
        • 1970-01-01
        • 1970-01-01
        • 2014-09-15
        • 2016-04-15
        • 1970-01-01
        • 2015-06-10
        相关资源
        最近更新 更多