- (void)getFile:(CDVInvokedUrlCommand*)command
{
NSString* baseURIstr = [command.arguments objectAtIndex:0];
CDVFilesystemURL* baseURI = [CDVFilesystemURL fileSystemURLWithString:baseURIstr];
NSString* requestedPath = [command.arguments objectAtIndex:1];
NSDictionary* options = [command.arguments objectAtIndex:2 withDefault:nil];
NSLog(@"baseURI %@", baseURIstr); // I ADDED THIS LINE
NSObject<CDVFileSystem> *fs = [self filesystemForURL:baseURI];
CDVPluginResult* result = [fs getFileForURL:baseURI requestedPath:requestedPath options:options];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}
The second line is where I suspect the problem lies.
[CDVFilesystemURL fileSystemURLWithString:baseURIstr]; returns nil. And I guess it's downhill from there. Not sure why this is happening or if this is indeed the problem. But this is all I came up with so far.
CDVFilesystemURL* baseURI = [CDVFilesystemURL fileSystemURLWithString:baseURIstr];
This call:
[CDVFilesystemURL fileSystemURLWithString:baseURIstr];
...leads to this call:
+ (CDVFilesystemURL *)fileSystemURLWithString:(NSString *)strURL
{
return [[CDVFilesystemURL alloc] initWithString:strURL];
}
...leads to this call:
- (id) initWithString:(NSString *)strURL
{
if ( self = [super init] ) {
NSURL *decodedURL = [NSURL URLWithString:strURL];
return [self initWithURL:decodedURL];
}
return nil;
}
Which is how I end up with nil for baseURIstr. So it appears [super init] is failing for some reason in initWithString:(NSString *)strURL.
Please disregard my last 3 debudding messages. None of that is happening anymore...
NSObject<CDVFileSystem> *fs = [self filesystemForURL:baseURI];
It always ends up with fs == null.
Tracing all the function calls I ended up in
- (NSString *)filesystemNameForLocalURI:(NSURL *)uri
{
NSLog(@"filesystemNameForLocalURI: [uri scheme] %@", [uri scheme]);
if ([[uri scheme] isEqualToString:kCDVFilesystemURLPrefix] && [[uri host] isEqualToString:@"localhost"]) {
NSArray *pathComponents = [uri pathComponents];
if (pathComponents != nil && pathComponents.count > 1) {
return [pathComponents objectAtIndex:1];
}
} else if ([[uri scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
return @"assets-library";
}
return nil;
}
The value of the argument uri was always "/" which was causing the above function to return nil. I went back to getFile in CDVFile.m "did the math" and discovered that
baseURI, which is an argument received from the Javascript side is "/" yet downstream it is expected to conform to a particular scheme as we saw above. So
I started looking on the JS side of the plugin to figure out what is wrong. When I looked here:
https://github.com/apache/cordova-plugin-file/tree/master/www
I noticed that there is a ios directory that contains two files:
FileSystem.js and Entry.js
This is the contents of FileSystem.js inside the ios directory:
FILESYSTEM_PROTOCOL = "cdvfile";module.exports = {__format__: function(fullPath) {var path = ('/'+this.name+(fullPath[0]==='/'?'':'/')+encodeURI(fullPath)).replace('//','/');return FILESYSTEM_PROTOCOL + '://localhost' + path;}
This is the code that constructs a "proper" uri, but it did NOT get pulled into my platforms/ios/www/plugins/org.apache.cordova.file.
I assume it was meant to happen automatically, but doesn't or didn't in my case. When I manually copy the above lines from ios specific
FileSystem.js to my FileSystem.js everything works. By contrast the iOS specific Entry.js DID get pulled into my platforms/ios/www/plugins/org.apache.cordova.file, so that's fine.
Looking at plugin.xml I noted the following lines:
<!-- ios specific file apis --><js-module src="www/ios/Entry.js" name="iosEntry"><merges target="window.Entry" /></js-module><js-module src="www/ios/FileSystem.js" name="iosFileSystem"><merges target="window.FileSystem" /></js-module>It looks like plugin.xml is setup correctly, so perhaps that problem is with iOS specific FileSystem.js? I am not sure why it's not getting pulled in automatically,
but I just tried it on fresh project by running:
cordova plugin add https://github.com/apache/cordova-plugin-file
cordova prepare
And it's still the same issue.
I am still not totally sure if it was my mistake somehow or if this is a bug in the plugin, but I wanted to post this here for everyone's benefit.
Small correction:
FILESYSTEM_PROTOCOL = "cdvfile";module.exports = {__format__: function(fullPath) {var path = ('/'+this.name+(fullPath[0]==='/'?'':'/')+encodeURI(fullPath)).replace('//','/');return FILESYSTEM_PROTOCOL + '://localhost' + path;}
You have to "extract the __format__ function, so that your final FinalSystem.js looks like this:cordova.define("org.apache.cordova.file.FileSystem", function(require, exports, module) { /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ var DirectoryEntry = require('./DirectoryEntry'); /** * An interface representing a file system * * @constructor * {DOMString} name the unique name of the file system (readonly) * {DirectoryEntry} root directory of the file system (readonly) */ var FileSystem = function(name, root) { this.name = name || null; if (root) { this.root = new DirectoryEntry(root.name, root.fullPath, this); } else { this.root = new DirectoryEntry(this.name, '/', this); } }; FileSystem.prototype.__format__ = function(fullPath) { return fullPath; }; FILESYSTEM_PROTOCOL = "cdvfile"; FileSystem.prototype.__format__ = function(fullPath) { var path = ('/'+this.name+(fullPath[0]==='/'?'':'/')+encodeURI(fullPath)).replace('//','/'); return FILESYSTEM_PROTOCOL + '://localhost' + path; }; module.exports = FileSystem; });
--
-- You received this message because you are subscribed to the Google
Groups "phonegap" group.
To post to this group, send email to phon...@googlegroups.com
To unsubscribe from this group, send email to
phonegap+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/phonegap?hl=en?hl=en
For more info on PhoneGap or to download the code go to www.phonegap.com
To compile in the cloud, check out build.phonegap.com
---
You received this message because you are subscribed to the Google Groups "phonegap" group.
To unsubscribe from this group and stop receiving emails from it, send an email to phonegap+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
FILESYSTEM_PROTOCOL = "cdvfile";module.exports = {__format__: function(fullPath) {var path = ('/'+this.name+(fullPath[0]==='/'?'':'/')+encodeURI(fullPath)).replace('//','/');return FILESYSTEM_PROTOCOL + '://localhost' + path;}