2

現在、Railsアプリでは、Carrierwaveを使用してファイルをAmazonS3にアップロードしています。ファイルセレクターとフォームを使用してファイルを選択して送信していますが、これはうまく機能します。

しかし、私は現在iPhoneアプリから投稿しようとしており、ファイルの内容を受け取っています。このデータを使用してファイルを作成し、Carrierwaveを使用してアップロードして、正しいパスを取得できるようにします。

ファイルモデルは次のもので構成されます。

path
file_name
id
user_id

ここで、pathはAmazonS3URLです。ファイルをビルドするために次のようなことをしたいと思います。

 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)

誰かが私を正しい方向に向けてくれることを本当に望んでいます。ありがとう!

4

2 に答える 2

2

これが私がiOSアプリケーションからcarrierwaveを介して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の2番目

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

次に、 AFNetworkingを使用したiPhoneアプリケーションからの呼び出し

-(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応答では、image.url属性がs3のurlに設定されたPhotoの新しいインスタンスを取得できます。

于 2012-10-04T14:15:28.223 に答える
0

わかりました、私は実用的な解決策を持っています。他の人が私の経験から学ぶことができるように、私が行ったことを最もよく説明します。ここに行きます:

写真を撮る 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];
}

レール側では、モバイル画像を処理するための特別な方法を設定しました。これは、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

このコードが完璧だと言っているわけではありません。しかし、それは私にとってはうまくいきます。誰かがそれを改善できると思うなら、私は提案を受け入れます。お役に立てれば!

于 2012-09-25T19:46:33.730 に答える