Modifying ObjectiveResource to support Multipart Uploads

1 view
Skip to first unread message

bi...@anides.com

unread,
Jun 22, 2009, 1:12:51 AM6/22/09
to ObjectiveResource
Hey Guys,

Apologies in advance for the lengthy post. I've made a handful (okay,
a rather large handful) of modifications to a private branch of
ObjectiveResource 1.1 and I hope that some of you will find these
updates useful.

I'm developing an iPhone application that needs to upload images to a
remote server via RESTful puts/posts. Scouring the Internet for
current best practices turned up virtually nothing; most shops seem to
be rolling their own solutions around multipart/form-data. However,
while researching libraries for deserializing XML, I came across your
wonderful framework and got to thinking that it may be possible to
modify it fit my needs.

I've made a tremendous deal of progress on my updates, despite a
couple of formidable obstacles, namely that

- I have very little experience with Objective-C
- I have NO experience with Rails (we're planning to use Java in our
production environment)

Having qualified this, I'd like to share my work with you all to get
feedback, particularly as it relates to the object model. You guys
have done an excellent job dividing up the classes into discreet
workers. I fear that my work may have blurred some of those
distinctions.

Central to my approach is the idea that serializable objects can
either encode themselves inline or choose to be added to a separate
attachments list. Thus, I've changed all derivatives of

toXMLElementExcluding:

to

toXMLElementExcluding:captureAttachments:.

(NOTE: If I can get the XML solution working correctly, I'll make a
similar change to all the JSON classes and categories.)

Passing in an empty Mutable Array will capture any attachments that
can't directly be serialized. If the attachment array contains
objects, the connection class can automagically reformat the request
as multipart.

Practically speaking, my updates resolve to a very simple change in
NSObject+ObjectiveResource.m. Calls to the connection class now look
like this (here shown as it appears in
updateRemoteAtPath:withResponse:):

NSMutableArray *attachments = [[[NSMutableArray alloc] init] retain];

Response *res = [Connection put:[self
convertToRemoteExpectedTypeAndCaptureAttachments:attachments] to:path
withAttachments:attachments
withUser:[[self class] getRemoteUser] andPassword:[[self
class] getRemotePassword]];

[attachments release];


I've also added a new composite class called ORBinaryData (which is
little more than an extension of NSData, coupled with a handful of
properties to capture things like MIME type and content id headers).
The ORBinaryData+XMLSerializableSupport category queries a new
SerializationConfig abstract class (which functions very similarly to
ObjectiveResourceConfig) to determine whether or not the binary data
should be serialized as an attachment. If attachment support is
disabled, the object is serialized inline via Base64 encoding.

To conclude, here is what I have working so far:

- Model classes now support the new ORBinaryData type. Users who want
to upload images to a remote server can store the picture data
directly inside their model. For example:


#import <Foundation/Foundation.h>
#import "ObjectiveResource.h"

@interface Student : NSObject {

NSString *studentId;

NSDate *createdAt;
NSDate *updatedAt;
NSString *firstname;
NSString *lastname;
NSString *gender;

ORBinaryData *image;

}


@property (nonatomic, retain) NSString *studentId;
@property (nonatomic, retain) NSDate *createdAt;
@property (nonatomic, retain) NSDate *updatedAt;
@property (nonatomic, retain) NSString *firstname;
@property (nonatomic, retain) NSString *lastname;
@property (nonatomic, retain) NSString *gender;
@property (nonatomic, retain) ORBinaryData *image;

@end


- Saving a model object, for example by calling

[student save];

will automatically generate either an application/xml post (with the
image data rendered as a Base64 string) or a multipart/related post
(with the image data stored as a binary attachment).

- I've created a new convenience method called setAllowMultipart in
ObjectiveResourceConfig. Setting this method toggles between
Multipart updates vs Base64 encoding. (It defaults to TRUE.)

[ObjectiveResourceConfig setAllowMultipart:FALSE];


Here is the work that lies ahead of me:

- I have yet to configure a Rails server to receive multipart
attachments (particularly those formated as multipart/related)

- For that matter, I haven't yet tested Base64 decryption in a Rails
environment. (Like I said, I have ZERO Rails experience.)

- I have to come up with a plan for deserializing ORBinaryData objects
with ObjectiveResource. I'm thinking about leveraging OR's connection
manager to automatically fetch image data if handed an empty
ORBinaryData object and a URL.

- I have to implement JSON support for ORBinaryData

- Code clean up, error handling, etc.

Here are some questions for you all:

- Everyone seems to be using multipart/form-data for uploading
images. But, based on my research, multipart/related seems like a
better logistical fit -- multipart/related allows you to bind a
resource to a specific XML or JSON node. Any idea why folks are using
form-data? Or how to hack Rails to support Multipart/related? (I
haven't played around with attachment_fu or Paperclip yet... so I have
no idea what'll happen if I submit multipart/related requests to
them.)

- Anyone interested in checking out my code, providing feedback? If
so, how do you want me to post it? I've got it sitting in a private
SVN repository at the moment. (Don't really have any GIT
experience... boy am I out of my element, or what?)

- Thoughts on my design decisions? Is this a useful contribution, or
am I swimming against the tide here?

Thanks for suffering through this novel. I look forward to hearing
from you!

Bill

bi...@anides.com

unread,
Jun 24, 2009, 2:57:48 AM6/24/09
to ObjectiveResource
For those of you interested in using ObjectiveResource to upload
images, I've added support for data serialization and Multipart
uploads. Here are the links to my git branches:

ObjectiveResource (multipart upload support)
git://github.com/AnidesBill/objectiveresource.git

ObjectiveSupport (binary serialization)
git://github.com/AnidesBill/objectivesupport.git

The code is very rough around the edges, so I could definitely use
some feedback. Thanks!

Bill

Jon Maddox

unread,
Jun 24, 2009, 3:00:36 AM6/24/09
to objectiv...@googlegroups.com
Awesome!

Kevin Elliott

unread,
Jun 24, 2009, 3:09:49 AM6/24/09
to objectiv...@googlegroups.com
Sweet! Submit a pull request so we can get it in the master :)

-Kevin
Reply all
Reply to author
Forward
0 new messages