Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add FileUploader plugin for iPhone

  • Loading branch information...
commit 930717936b95e43c0e9c9438efcdee1de3dd4fce 1 parent 072a8a0
@ascorbic ascorbic authored
View
34 iPhone/FileUploader/FileUploader.h
@@ -0,0 +1,34 @@
+//
+// FileUploader.h
+//
+// Created by Matt Kane on 14/01/2011.
+// Copyright 2011 Matt Kane. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "PhoneGapCommand.h"
+
+@interface FileUploader : PhoneGapCommand {
+
+}
+- (void) upload:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
+- (void) uploadByUri:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
+- (void) uploadFile:(NSURL*)file toServer:(NSString*)server withParams:(NSMutableDictionary*)params fileKey:(NSString*)fileKey fileName:(NSString*)fileName mimeType:(NSString*)mimeType successCallback:(NSString*)successCallback failCallback:(NSString*)failCallback progressCallback:(NSString*)progressCallback;
+@end
+
+
+@interface FileUploadDelegate : NSObject {
+ NSString* successCallback;
+ NSString* failCallback;
+ NSString* progressCallback;
+ FileUploader* command;
+ int uploadIdx;
+}
+
+@property (nonatomic, copy) NSString* successCallback;
+@property (nonatomic, copy) NSString* failCallback;
+@property (nonatomic, copy) NSString* progressCallback;
+@property (nonatomic, retain) NSMutableData* responseData;
+@property (nonatomic, retain) FileUploader* command;
+
+@end;
View
217 iPhone/FileUploader/FileUploader.m
@@ -0,0 +1,217 @@
+//
+// FileUploader.m
+//
+// Created by Matt Kane on 14/01/2011.
+// Copyright 2011 Matt Kane. All rights reserved.
+//
+
+#import "FileUploader.h"
+
+
+@implementation FileUploader
+
+- (void) upload:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ NSUInteger argc = [arguments count];
+
+ if(argc < 2) {
+ return;
+ }
+
+ NSString* successCallback = [arguments objectAtIndex:0];
+ NSString* failCallback = [arguments objectAtIndex:1];
+
+ if(argc < 6) {
+ [self writeJavascript: [NSString stringWithFormat:@"%@(\"Argument error\");", failCallback]];
+ return;
+ }
+
+ NSString* progressCallback = [arguments objectAtIndex:2];
+ NSString* server = [arguments objectAtIndex:3];
+ NSURL* file = [NSURL fileURLWithPath:[arguments objectAtIndex:4] isDirectory: NO];
+ NSString* fileKey = nil;
+ NSString* fileName = nil;
+ NSString* mimeType = nil;
+
+ if(argc > 5) {
+ fileKey = [arguments objectAtIndex:5];
+ }
+
+ if(argc > 6) {
+ fileName = [arguments objectAtIndex:6];
+ }
+
+ if(argc > 7) {
+ mimeType = [arguments objectAtIndex:7];
+ }
+ [self uploadFile:file toServer:server withParams:options fileKey:fileKey fileName:fileName mimeType:mimeType successCallback:successCallback failCallback:failCallback progressCallback:progressCallback];
+}
+
+- (void) uploadByUri:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ NSUInteger argc = [arguments count];
+
+ if(argc < 2) {
+ return;
+ }
+
+ NSString* successCallback = [arguments objectAtIndex:0];
+ NSString* failCallback = [arguments objectAtIndex:1];
+
+ if(argc < 6) {
+ [self writeJavascript: [NSString stringWithFormat:@"%@(\"Argument error\");", failCallback]];
+ return;
+ }
+ NSString* progressCallback = [arguments objectAtIndex:2];
+ NSString* server = [arguments objectAtIndex:3];
+ NSURL* file = [NSURL URLWithString:[arguments objectAtIndex:4]];
+ NSString* fileKey = nil;
+ NSString* fileName = nil;
+ NSString* mimeType = nil;
+
+ if(argc > 5) {
+ fileKey = [arguments objectAtIndex:5];
+ }
+
+ if(argc > 6) {
+ fileName = [arguments objectAtIndex:6];
+ }
+
+ if(argc > 7) {
+ mimeType = [arguments objectAtIndex:7];
+ }
+ [self uploadFile:file toServer:server withParams:options fileKey:fileKey fileName:fileName mimeType:mimeType successCallback:successCallback failCallback:failCallback progressCallback:progressCallback];
+}
+
+- (void) uploadFile:(NSURL*)file toServer:(NSString*)server withParams:(NSMutableDictionary*)params fileKey:(NSString*)fileKey fileName:(NSString*)fileName mimeType:(NSString*)mimeType successCallback:(NSString*)successCallback failCallback:(NSString*)failCallback progressCallback:(NSString*)progressCallback
+{
+
+ if (![file isFileURL]) {
+ [self writeJavascript: [NSString stringWithFormat:@"%@(\"Is not a valid file\");", failCallback]];
+ return;
+ }
+
+ if(!fileName) {
+ fileName = @"image.jpg";
+ }
+
+ if(!mimeType) {
+ mimeType = @"image/jpeg";
+ }
+
+ if(!fileKey) {
+ fileKey = @"file";
+ }
+
+ NSString *boundary = @"*****com.beetight.formBoundary";
+
+ NSURL *url = [NSURL URLWithString:server];
+
+ NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
+ [req setHTTPMethod:@"POST"];
+
+ NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
+ [req setValue:contentType forHTTPHeaderField:@"Content-type"];
+ NSString* userAgent = [[webView request] valueForHTTPHeaderField:@"User-agent"];
+ if(userAgent) {
+ [req setValue: userAgent forHTTPHeaderField:@"User-agent"];
+ }
+
+ NSData *imageData = [NSData dataWithContentsOfURL:file];
+
+ if(!imageData) {
+ [self writeJavascript: [NSString stringWithFormat:@"%@(\"Could not open file\");", failCallback]];
+ return;
+ }
+
+ NSMutableData *postBody = [NSMutableData data];
+
+ NSEnumerator *enumerator = [params keyEnumerator];
+ id key;
+ id val;
+ while ((key = [enumerator nextObject])) {
+ val = [params objectForKey:key];
+ if(!val || val == [NSNull null]) {
+ continue;
+ }
+ [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[val dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
+ }
+
+ [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fileKey, fileName] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimeType] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:imageData];
+ [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [req setHTTPBody:postBody];
+
+ FileUploadDelegate* delegate = [[[FileUploadDelegate alloc] init] retain];
+ delegate.command = self;
+ delegate.successCallback = successCallback;
+ delegate.failCallback = failCallback;
+ delegate.progressCallback = progressCallback;
+
+ NSURLConnection* connection = [[NSURLConnection connectionWithRequest:req delegate:delegate] retain];
+}
+
+@end
+
+
+@implementation FileUploadDelegate
+
+@synthesize successCallback, failCallback, progressCallback, responseData, command;
+
+- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
+{
+ if(!self.progressCallback) {
+ return;
+ }
+ if (uploadIdx++ % 10 == 0) {
+ [command writeJavascript: [NSString stringWithFormat:@"%@(%d, %d);", self.progressCallback, totalBytesWritten, totalBytesExpectedToWrite]];
+ }
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection
+{
+ NSString* response = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
+ NSLog(@"reponse: %@", response);
+ NSString* js = [NSString stringWithFormat:@"%@(\"%@\");", self.successCallback, [response stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+ [command writeJavascript: js];
+ [connection autorelease];
+ [self autorelease];
+}
+
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
+{
+ [command writeJavascript: [NSString stringWithFormat:@"%@(\"%@\");", self.failCallback, [[error localizedDescription] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
+ [connection autorelease];
+ [self autorelease];
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
+{
+ [responseData appendData:data];
+}
+
+- (id) init
+{
+ if (self = [super init]) {
+ self.responseData = [NSMutableData data];
+ uploadIdx = 0;
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ [successCallback release];
+ [failCallback release];
+ [responseData release];
+ [command release];
+ [super dealloc];
+}
+
+
+@end;
View
61 iPhone/FileUploader/README.md
@@ -0,0 +1,61 @@
+# File Uploader plugin for Phonegap - iPhone version #
+By Matt Kane
+
+Enables multipart/mime file uploads.
+
+## Adding the Plugin to your project ##
+
+Copy the .h and .m file to the Plugins directory in your project. Copy the .js file to your www directory and reference it from your html file(s).
+
+
+## Using the plugin ##
+The plugin creates the object `window.plugins.fileUploader` with two methods, `upload` and `uploadByUri`.
+These are identical except for the format of the reference to the file to upload. `upload` takes an
+absolute path, e.g. `/var/tmp/photo_001.jpg`, while `uploadByUri` takes a file:// Uri,
+e.g. `file://localhost/var/tmp/photo_001.jpg`.
+The full params are as follows:
+
+* server URL of the server that will receive the file
+* file Absolute path or uri of the file to upload
+* fileKey Parameter name of the file
+* params Object with key: value params to send to the server
+* fileName Filename to send to the server. Defaults to image.jpg
+* mimeType Mimetype of the uploaded file. Defaults to image/jpeg
+* success Success callback. Passed the response data from the server as a string.
+* fail Error callback. Passed the error message.
+* progress Called on upload progress. Signature should be function(bytesUploaded, totalBytes)
+
+This is under development, and the API is likely to change.
+
+
+## BUGS AND CONTRIBUTIONS ##
+The latest bleeding-edge version is available [on GitHub](http://github.com/ascorbic/phonegap-plugins/)
+If you have a patch, fork my repo and send me a pull request. Submit bug reports on GitHub, please.
+
+## Licence ##
+
+The MIT License
+
+Copyright (c) 2011 Matt Kane
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+
+
View
76 iPhone/FileUploader/fileuploader.js
@@ -0,0 +1,76 @@
+/**
+ * Phonegap File Upload plugin
+ * iPhone version
+ * Copyright (c) Matt Kane 2011
+ *
+ */
+var FileUploader = function() {
+
+}
+
+
+/**
+ * Given a file:// url, uploads the file to the server as a multipart/mime request
+ *
+ * @param server URL of the server that will receive the file
+ * @param file file:// uri of the file to upload
+ * @param fileKey Parameter name of the file
+ * @param params Object with key: value params to send to the server
+ * @param fileName Filename to send to the server. Defaults to image.jpg
+ * @param mimeType Mimetype of the uploaded file. Defaults to image/jpeg
+ * @param success Success callback. Passed the response data from the server as a string.
+ * @param fail Error callback. Passed the error message.
+ * @param progress Called on upload progress. Signature should be function(bytesUploaded, totalBytes)
+ */
+FileUploader.prototype.uploadByUri = function(server, file, params, fileKey, fileName, mimeType, success, fail, progress) {
+ this._doUpload('uploadByUri', server, file, params, fileKey, fileName, mimeType, success, fail, progress);
+};
+
+/**
+ * Given absolute path, uploads the file to the server as a multipart/mime request
+ *
+ * @param server URL of the server that will receive the file
+ * @param file Absolute path of the file to upload
+ * @param fileKey Parameter name of the file
+ * @param params Object with key: value params to send to the server
+ * @param fileName Filename to send to the server. Defaults to image.jpg
+ * @param mimeType Mimetype of the uploaded file. Defaults to image/jpeg
+ * @param success Success callback. Passed the response data from the server as a string.
+ * @param fail Error callback. Passed the error message.
+ * @param progress Called on upload progress. Signature should be function(bytesUploaded, totalBytes)
+ */
+FileUploader.prototype.upload = function(server, file, params, fileKey, fileName, mimeType, success, fail, progress) {
+ this._doUpload('upload', server, file, params, fileKey, fileName, mimeType, success, fail, progress);
+};
+
+FileUploader.prototype._doUpload = function(method, server, file, params, fileKey, fileName, mimeType, success, fail, progress) {
+ if (!params) {
+ params = {}
+ }
+
+ var key = 'f' + this.callbackIdx++;
+ window.plugins.fileUploader.callbackMap[key] = {
+ success: function(result) {
+ success(result);
+ delete window.plugins.fileUploader.callbackMap[key]
+ },
+ fail: function(result) {
+ fail(result);
+ delete window.plugins.fileUploader.callbackMap[key]
+ },
+ progress: progress
+ }
+ var callback = 'window.plugins.fileUploader.callbackMap.' + key;
+
+ return PhoneGap.exec('FileUploader.' + method, callback + '.success', callback + '.fail', callback + '.progress', server, file, fileKey, fileName, mimeType, params);
+}
+
+FileUploader.prototype.callbackMap = {};
+FileUploader.prototype.callbackIdx = 0;
+
+PhoneGap.addConstructor(function() {
+ if(!window.plugins) {
+ window.plugins = {};
+ }
+ window.plugins.fileUploader = new FileUploader();
+});
Please sign in to comment.
Something went wrong with that request. Please try again.