Skip to content
This repository has been archived by the owner on Mar 16, 2019. It is now read-only.

Commit

Permalink
#44 successfully upload file to Firebase storage
Browse files Browse the repository at this point in the history
  • Loading branch information
wkh237 committed Jul 21, 2016
1 parent 113e07a commit 9607725
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 152 deletions.
1 change: 1 addition & 0 deletions src/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ function writeFile(path:string, data:string | Array<number>, encoding:?string):P

function appendFile(path:string, data:string | Array<number>, encoding:?string):Promise {
encoding = encoding || 'utf8'
console.log('fs append file', data, encoding)
if(typeof path !== 'string')
return Promise.reject('Invalid argument "path" ')
if(encoding.toLocaleLowerCase() === 'ascii') {
Expand Down
63 changes: 23 additions & 40 deletions src/ios/RNFetchBlobFS.m
Original file line number Diff line number Diff line change
Expand Up @@ -213,49 +213,32 @@ + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString
encoding = [encoding lowercaseString];
if(![fm fileExistsAtPath:folder]) {
[fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
[fm createFileAtPath:path contents:nil attributes:nil];
}
// if file exists, write file using encoding
if(![fm fileExistsAtPath:path]) {
if([encoding isEqualToString:@"base64"]){
NSData * byteData = [[NSData alloc] initWithBase64EncodedString:data options:0];
[fm createFileAtPath:path contents:byteData attributes:NULL];
}
// write file from file
else if([encoding isEqualToString:@"uri"]) {
[[self class] writeFileFromFile:data toFile:path append:append];
resolve([NSNull null]);
return;
}
//TODO: from buffer
// else if ([encoding isEqualToString:@"buffer"]){
// }
// write data as UTF8 string
else
[fm createFileAtPath:path contents:[data dataUsingEncoding:NSUTF8StringEncoding] attributes:NULL];
if(err != nil) {
reject(@"RNFetchBlob writeFile Error", @"could not create file at path", path);
return;
}
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
NSData * content = nil;
if([encoding isEqualToString:@"base64"]) {
content = [[NSData alloc] initWithBase64EncodedString:data options:0];
}
else if([encoding isEqualToString:@"uri"]) {
[[self class] writeFileFromFile:data toFile:path append:append];
resolve([NSNull null]);
return;
}
// file does not exists, create one
else {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
NSData * content = nil;
if([encoding isEqualToString:@"base64"]) {
content = [[NSData alloc] initWithBase64EncodedString:data options:0];
}
else if([encoding isEqualToString:@"uri"]) {
[[self class] writeFileFromFile:data toFile:path append:append];
resolve([NSNull null]);
return;
}
else {
content = [data dataUsingEncoding:NSUTF8StringEncoding];
}
if(append == YES) {
[fileHandle seekToEndOfFile];
[fileHandle writeData:content];
[fileHandle closeFile];
}
else {
[content writeToFile:path atomically:YES];
}
content = [data dataUsingEncoding:NSUTF8StringEncoding];
}
if(append == YES) {
[fileHandle seekToEndOfFile];
[fileHandle writeData:content];
[fileHandle closeFile];
}
else {
[content writeToFile:path atomically:YES];
}
fm = nil;
resolve([NSNull null]);
Expand Down
2 changes: 0 additions & 2 deletions src/ios/RNFetchBlobNetwork.m
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ - (void) sendRequest:(NSDictionary * _Nullable )options

if(path != nil)
destPath = path;
// else
// destPath = [RNFetchBlobFS getTempPath:cacheKey withExtension:[self.options valueForKey:CONFIG_FILE_EXT]];
}
else
{
Expand Down
50 changes: 23 additions & 27 deletions src/ios/RNFetchBlobReqBuilder.m
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,13 @@ +(void) buildOctetRequest:(NSDictionary *)options
if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
// generate octet-stream body
if(body != nil) {


// when headers does not contain a key named "content-type" (case ignored), use default content type
if([[self class] getHeaderIgnoreCases:@"content-type" fromHeaders:mheaders] == nil)
{
[mheaders setValue:@"application/octet-stream" forKey:@"Content-Type"];
}

// when body is a string contains file path prefix, try load file from the path
if([body hasPrefix:FILE_PREFIX]) {
NSString * orgPath = [body substringFromIndex:[FILE_PREFIX length]];
Expand All @@ -95,10 +101,6 @@ +(void) buildOctetRequest:(NSDictionary *)options
{
[RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
[request setHTTPBody:content];
if([mheaders valueForKey:@"content-type"] == nil)
{
[mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
}
[request setHTTPMethod: method];
[request setAllHTTPHeaderFields:mheaders];
onComplete(request, [content length]);
Expand All @@ -110,24 +112,22 @@ +(void) buildOctetRequest:(NSDictionary *)options
}
// otherwise convert it as BASE64 data string
else {
// the body is BASE64 encoded string
if(([mheaders valueForKey:@"content-type"] == nil && [mheaders valueForKey:@"Content-Type"] == nil) ||
([[[mheaders valueForKey:@"content-type"] lowercaseString] isEqualToString:@"application/octet-stream"] ||
[[[mheaders valueForKey:@"Content-Type"] lowercaseString] isEqualToString:@"application/octet-stream"]))

NSString * cType = [[self class]getHeaderIgnoreCases:@"content-type" fromHeaders:mheaders];
// when content-type is application/octet* decode body string using BASE64 decoder
if([[cType lowercaseString] hasPrefix:@"application/octet"])
{
blobData = [[NSData alloc] initWithBase64EncodedString:body options:0];
[mheaders setValue:@"application/octet-stream" forKey:@"Content-Type"];
[request setHTTPBody:blobData];
size = [blobData length];
}
// use the body string as is
// otherwise use the body as-is
else
{
size = [body length];
[request setHTTPBody: [body dataUsingEncoding:NSUTF8StringEncoding]];
}
}

}
}

Expand All @@ -138,21 +138,6 @@ +(void) buildOctetRequest:(NSDictionary *)options
});
}

//+(void) buildEncodedRequest:(NSDictionary *)options
// taskId:(NSString *)taskId
// method:(NSString *)method
// url:(NSString *)url
// headers:(NSDictionary *)headers
// body:(NSString *)body
// onComplete:(void(^)(NSURLRequest * req, long bodyLength))onComplete
//{
// NSMutableData * formData = [[NSMutableData alloc] init];
//
// [formData appendData:[[NSString stringWithFormat:@"%@", body] dataUsingEncoding:NSUTF8StringEncoding]];
// onComplete(formData);
//}


+(void) buildFormBody:(NSArray *)form boundary:(NSString *)boundary onComplete:(void(^)(NSData * formData))onComplete
{
NSMutableData * formData = [[NSMutableData alloc] init];
Expand Down Expand Up @@ -225,5 +210,16 @@ void __block (^getFieldData)(id field) = ^(id field)
}
}

+(NSString *) getHeaderIgnoreCases:(NSString *)field fromHeaders:(NSMutableArray *) headers {

NSString * normalCase = [headers valueForKey:field];
NSString * ignoredCase = [headers valueForKey:[field lowercaseString]];
if( normalCase != nil)
return normalCase;
else
return ignoredCase;

}


@end
139 changes: 59 additions & 80 deletions src/polyfill/Blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default class Blob {

_ref:string = null;
_blobCreated:boolean = false;
_onCreated:() => void;
_onCreated:Array<any> = [];

static Instances:any = {}

Expand All @@ -35,86 +35,44 @@ export default class Blob {
this.cacheName = getBlobName()
this.isRNFetchBlobPolyfill = true
this.type = mime
log.verbose('Blob constructor called' , data, 'mime', mime)

if(typeof data === 'string') {
// content from file
if(data.startsWith('RNFetchBlob-file://')) {
this._ref = data
this._blobCreated = true
if(typeof this._onCreated === 'function')
this._onCreated(this)
}
// content from variable need create file
else {
log.verbose('create Blob cache file ..')
this._ref = RNFetchBlob.wrap(blobCacheDir + this.cacheName)
let encoding = 'utf8'
if(typeof data === 'string' && String(mime).match('application/octet') )
encoding = 'base64'
else if(Array.isArray(data))
encoding = 'ascii'

this.init(data, encoding)
.then(() => {
log.verbose('init executed ')
if(typeof this._onCreated === 'function')
this._onCreated(this)
})
.catch((err) => {
log.error('RNFetchBlob cannot create Blob', err)
})
}
log.verbose('Blob constructor called', 'mime', mime)
this._ref = blobCacheDir + this.cacheName
let p = null
// content from file
if(typeof data === 'string' && data.startsWith('RNFetchBlob-file://')) {
log.verbose('create Blob cache file from file path')
this._ref = data
p = Promise.resolve()
}
// TODO : handle mixed blob array
// content from variable need create file
else if(typeof data === 'string') {
log.verbose('create Blob cache file from string')
let encoding = 'utf8'
if(String(mime).match('application/octet'))
encoding = 'base64'
else if(Array.isArray(data))
encoding = 'ascii'
// create cache file
p = fs.writeFile(this._ref, data, encoding)

}
// when input is an array of mixed data types, create a file cache
else if(Array.isArray(data)) {
this._ref = RNFetchBlob.wrap(blobCacheDir + this.cacheName)
createMixedBlobData(this._ref, data)
.then(() => {
if(typeof this._onCreated === 'function')
this._onCreated(this)
})
log.verbose('create Blob cache file from mixed array', data)
p = createMixedBlobData(this._ref, data)
}
p && p.then(() => {
this._invokeOnCreateEvent()
})
.catch((err) => {
log.error('RNFetchBlob cannot create Blob : '+ this._ref)
})

}

onCreated(fn:() => void) {
log.verbose('register blob onCreated')
if(this._blobCreated)
fn()
else
this._onCreated = fn
}

/**
* Create blob file cache
* @nonstandard
* @param {string | Array} data Data to create Blob file
* @param {'base64' | 'utf8' | 'ascii'} encoding RNFetchBlob fs encoding
* @return {Promise}
*/
init(data, encoding):Promise {
return new Promise((resolve, reject) => {
fs.exists(blobCacheDir)
.then((exist) => {
log.verbose('blob cache folder exist', blobCacheDir, exist)
let path = String(this._ref).replace('RNFetchBlob-file://', '')
log.verbose('create cache file', path)
if(!exist)
return fs.mkdir(blobCacheDir)
.then(() => fs.createFile(path, data, encoding))
else
return fs.createFile(path, data, encoding)
})
.then(() => {
this._blobCreated = true
resolve()
})
.catch((err) => {
reject(err)
})
})

log.verbose('register blob onCreated', this._onCreated.length)
this._onCreated.push(fn)
}

/**
Expand Down Expand Up @@ -146,6 +104,21 @@ export default class Blob {
return fs.unlink(this._ref)
}

clearCache() {

}

_invokeOnCreateEvent() {
log.verbose('invoke create event')
this._blobCreated = true
let fns = this._onCreated
for(let i in fns) {
if(typeof fns[i] === 'function')
fns[i](this)
}
delete this._onCreated
}

}

/**
Expand All @@ -164,15 +137,21 @@ function getBlobName() {
* @return {Promise}
*/
function createMixedBlobData(ref, dataArray) {
let p = fs.createFile(ref, '')
let p = fs.writeFile(ref, '')
let args = []
for(let i in dataArray) {
let part = dataArray[i]
if(part instanceof Blob)
p.then(() => fs.appendFile(ref, part.getRNFetchBlobRef()), 'uri')
args.push([ref, part.getRNFetchBlobRef(), 'uri'])
else if(typeof part === 'string')
args.push([ref, part, 'utf8'])
else if (Array.isArray(part))
p.then(() => fs.appendFile(ref), part, 'ascii')
else
p.then(() => fs.appendFile(ref), part, 'utf8')
args.push([ref, part, 'ascii'])
}
return p
return p.then(() => {
let promises = args.map((p) => {
return fs.appendFile.call(this, ...p)
})
return Promise.all(promises)
})
}
7 changes: 4 additions & 3 deletions src/polyfill/XMLHttpRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
this._upload = new XMLHttpRequestEventTarget()
log.verbose(typeof body, body instanceof FormData)
if(Array.isArray(body)) {
// TODO
if(body instanceof Blob) {
body = RNFetchBlob.wrap(body.getRNFetchBlobRef())
}
this.dispatchEvent('loadstart')
Expand Down Expand Up @@ -211,7 +212,7 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
}

_onDone(resp) {
log.verbose('XMLHttpRequest done', resp.text())
log.verbose('XMLHttpRequest done', this)
this.statusText = '200 OK'
this._status = 200
switch(resp.type) {
Expand Down

0 comments on commit 9607725

Please sign in to comment.