FatFractal customer forums



Author Topic: Posting Text File to Extension  (Read 3405 times)

kwylez

  • Newbie
  • *
  • Posts: 27
    • View Profile
Posting Text File to Extension
« on: December 19, 2013, 09:14:08 AM »
I'm working on a remote logger and when the app goes into the background, then all the files (text files in iOS app) are uploaded to an endpoint, parsed and logging information saved.  The reason I've it setup like this is
1) I wanted to keep the network requests to a minimum since there is a hard limit on the number of network requests that the phone can make (want to save all resources for the app functionality itself)
2) NSURLBackgroundSessions only support uploads if they are files.

How to get the posted binary data from the extension request body, convert it to a JSON string and then save it to NoServer?

If I print out the value of ff.getExtensionRequestData().httpContent I get: java.io.FileInputStream@2ff246ab so I'm assuming I can convert that into json object?

// Extension

Code: [Select]

var ff  = require('ffef/FatFractal');
var bin = require ('binary');

function EventLog() {

  this.clazz = 'EventLog';

  return this;
}

exports.addLog = function() {

    var data             = ff.getExtensionRequestData();
    var eventLog         = null;
    var eventLogObject   = data.httpContent;
    var eventLogInstance = null;
   
    if (data.httpMethod.toLowerCase() !== 'post') {
     
      ff.response().responseCode  = "405";
      ff.response().statusMessage = "You must use POST method";
      ff.response().mimeType      = "application/json";
      ff.response().result        = JSON.stringify("REJECTED");

    } else {

      eventLog = new EventLog();

      for (key in eventLogObject) {
        eventLog[key] = eventLogObject[key];
      }

      eventLogInstance = ff.createObjAtUri(eventLog, '/EventLogs');
     
      if (eventLogInstance === null) {
 
        ff.response().responseCode  = "500";
        ff.response().statusMessage = "Event Log Save Failed";
        ff.response().mimeType      = "application/json";
        ff.response().result        = {'message' : 'The Event Log failed to save'};

        return;
      }

      ff.response().responseCode  = "200";
      ff.response().statusMessage = "Event Log Save Success";
      ff.response().mimeType      = "application/json";
      ff.response().result        = {'message' : 'processing finished'};
    }
};


// iOS Snippet
Code: [Select]
- (void)sendFilesInBackground:(NSArray *)files {

 BOOL goodSetup = [self.urlString length];

 NSAssert(goodSetup, @"Error: FFArmstrongSession must have a url string!");
 
 for (NSString * path in files) {
   
   if ([path rangeOfString:FFArmstrongLogFilePrefix].location != NSNotFound && path) {
   
     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]];
     
     request.HTTPMethod = @"POST";
     
     NSMutableDictionary *headers = [NSMutableDictionary dictionary];

//      [headers setValue:@"application/json" forKey:@"Content-Type"];
     [headers setValue:@"application/octet-stream" forKey:@"Content-Type"];
     [headers setValue:path forKey:@"LocalPath"];
     
     request.allHTTPHeaderFields = headers;

     NSURL *loggerURL = [NSURL fileURLWithPath:path];
     
     NSLog(@"url: %@", self.urlString);
     
     NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request
                                                                     fromFile:loggerURL];
     [uploadTask resume];
   }
 }
}

jonnycools

  • Jr. Member
  • **
  • Posts: 74
    • View Profile
Re: Posting Text File to Extension
« Reply #1 on: December 19, 2013, 08:22:01 PM »
Three things.

1) You can store the files on the server in the BYTEARRAY if you like.

2) if you are going to convert them into strings why not just send the strings over the extension request.

3) the SDK proves methods for interacting with extensions as well as sending content to it

- iOS

- (void)sendFilesInBackground:(NSArray *)files {

[[FatFractal main] postObj:files toExtension:@"ExtensionName" onComplete:^(NSError *theErr, id theObj, NSHTTPURLResponse *theResponse) {
         
       }];

}

- JS

exports.extensionName = function()
{

   var filesArray = data.httpContent;

//do stuff


   var response = ff.response();

   response.responseCode = 200;

   response.statusMessage = "";

   response.result = "Result";

   response.mimeType = "application/json";

}



gkc

  • Administrator
  • *****
  • Posts: 375
    • View Profile
Re: Posting Text File to Extension
« Reply #2 on: December 20, 2013, 02:18:56 PM »
If you need to use NSURLSessionUploadTask (or in general you want to POST binary data directly to an extension) then you should do the following things:

(1) Ensure you are POSTing with Content-Type application/octet-stream in order to ensure it is accessible on the server-side via a binary stream
(2) From the client-side you should set headers as follows so that the logged-in user context will be preserved
Code: [Select]
[request setValue:ff.loggedInUserGuid forHTTPHeaderField:@"X-Ff-Auth-User-Guid"];
[request setValue:ff.loggedInSessionId forHTTPHeaderField:@"X-Ff-Auth-Session-Id"];
(3) On server-side, here's a simple example which uses the CommonJS 'io' package, expects text as the content, and just echoes it back:
Code: [Select]
exports.testBlobPassThrough = function() {
    var io = require('io');
    print("httpContent: " + ff.getExtensionRequestData().httpContent);
    var stream = new io.Stream(ff.getExtensionRequestData().httpContent);
    print("Got stream from httpContent: " + stream);
    var byteString = stream.read();
    print("Got ByteString from stream: " + byteString);
    var string = byteString.decodeToString("UTF-8");
    print("Got String from ByteString:" + string);
    ff.response().wrap = false;
    ff.response().result = string;
};

FYI: NoServer leverages the wonderful RingoJS project for its CommonJS modules. Have a look at the ringojs site here: http://ringojs.org
« Last Edit: December 31, 2013, 06:39:43 AM by gkc »

kwylez

  • Newbie
  • *
  • Posts: 27
    • View Profile
Re: Posting Text File to Extension
« Reply #3 on: January 05, 2014, 04:00:05 PM »
Gary this is great. I'm updating my code now and will update this once I'm done

kwylez

  • Newbie
  • *
  • Posts: 27
    • View Profile
Re: Posting Text File to Extension
« Reply #4 on: January 05, 2014, 09:14:23 PM »
Here is a quick snippet of the code that I used

iOS client

Code: [Select]
....
  for (NSString *path in files) {
   
    if ([path rangeOfString:FFArmstrongLogFilePrefix].location != NSNotFound && path) {
   
      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]];
     
      request.HTTPMethod = @"POST";
     
      NSMutableDictionary *headers = [NSMutableDictionary dictionary];

      [headers setValue:@"application/octet-stream" forKey:@"Content-Type"];
     
      request.allHTTPHeaderFields = headers;

      NSURL *loggerURL = [NSURL fileURLWithPath:path];
     
      NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request
                                                                      fromFile:loggerURL];
      [uploadTask resume];
    }
  }

FF

Code: [Select]

var ff  = require('ffef/FatFractal');
var bin = require ('binary');

function EventLog() {

  this.clazz = 'EventLog';

  return this;
}

exports.addLog = function() {

  var io = require('io');
  print("httpContent: " + ff.getExtensionRequestData().httpContent);
 
  var stream = new io.Stream(ff.getExtensionRequestData().httpContent);
  print("Got stream from httpContent: " + stream);
 
  var byteString = stream.read();
  print("Got ByteString from stream: " + byteString);
 
  var string = byteString.decodeToString("UTF-8");
  print("Got String from ByteString:" + string);

  var eventLogObject = JSON.parse(string);
  var eventLog       = new EventLog();

  for (key in eventLogObject) {
    eventLog[key] = eventLogObject[key];
  }

  eventLogInstance = ff.createObjAtUri(eventLog, '/EventLogs');
 
  if (eventLogInstance === null) {
 
      ff.response().responseCode  = "500";
      ff.response().statusMessage = "Event Log Save Failed";
      ff.response().mimeType      = "application/json";
      ff.response().result        = {'message' : 'The Event Log failed to save'};

      return;
  }

  ff.response().responseCode  = "200";
  ff.response().statusMessage = "Event Log Save Success";
  ff.response().mimeType      = "application/json";
  ff.response().result        = {'message' : 'processing finished'};
};



gkc

  • Administrator
  • *****
  • Posts: 375
    • View Profile
Re: Posting Text File to Extension
« Reply #5 on: January 06, 2014, 11:06:03 AM »
Very nice! I presume you're not setting the auth headers because you are using an API key approach instead?

kwylez

  • Newbie
  • *
  • Posts: 27
    • View Profile
Re: Posting Text File to Extension
« Reply #6 on: January 08, 2014, 08:58:22 PM »
Yes that is correct Gary.

 

Copyright © FatFractal customer forums