I have to download images and save it into my local database. So I am storing the images in NSData and than inserting it into local database. But there are atleast 50 images coming from the server so storing the images into NSData and then inserting into local database it taking more time. Is there any solution so that it will consume less time.
Please suggest me.
The more common way to handle image download from the internet is just cache it to the memory(NSURLCache) or disk(SDWebImageView). and only save the 'image url' to the database.
The Cache mechanism will find the image next image you use that URL.
Try to save the files on the disc, and put file paths into data base instead of inserting BLOBs into database
In another words:
Your database will contain images metadata and absolute paths to files
You can do even this:
Create file path
While downloading your image append bytes to the file at this
created file path ( several ways to do - manually by using
NSURLConnection, or use some libs like AFHTTPConnection with NSStream
attached)
Check if everything is OK, then put the file path string into your
database or clean the file and report about error
But it is better to:
Download file to the temporary directory
Check if everything is ok, then move to the permanent directory and store file path in data base
Clean your temporary directory if needed
Clean your temporary directory regulary (By the way, iOS will clean it sometimes)
just try with HCDownload it is a component that you use for downloading image from url. just download this class and use below code it is very easy. once your download is complete then delegate method finishedDownloadingURL is called for all images one by one then store its path (path of image where you stored) on database.
HCDownload
use this as describe below.
.h file
#import "HCDownloadViewController.h"
#interface HomeViewController_iPhone : UIViewController<HCDownloadViewControllerDelegate>
{
HCDownloadViewController *tblDownloadHairStyle;
}
#property (nonatomic,retain) HCDownloadViewController *tblDownloadHairStyle;
.m file
#synthesize tblDownloadHairStyle;
- (void)viewDidLoad
{
[super viewDidLoad];
tblDownloadHairStyle=[[HCDownloadViewController alloc] init];
tblDownloadHairStyle.delegate=self;
}
//Where you download the image
[self createDocumentDirectory:#"MyFolder"]; //create folder for save photo
NSString *pathHair=[self getDocumentDirectoryPath:#"MyFolder"];
tblDownloadHairStyle.downloadDirectory = pathHair;
// your other code just get the image path
NSString *strimage_path=[hairDictonary objectForKey:#"image_path"];
strimage_path=[NSString stringWithFormat:#"http://yoururr.com/%#",strimage_path];
[tblDownloadHairStyle downloadURL:[NSURL URLWithString:strimage_path] userInfo:hairDictonary];
#pragma mark-
#pragma mark-HCDownloadViewController Delegate Method
- (void)downloadController:(HCDownloadViewController *)vc startedDownloadingURL:(NSURL *)url userInfo:(NSDictionary *)userInfo {
NSLog(#"startedDownloadingURL=%#",url);
}
- (void)downloadController:(HCDownloadViewController *)vc finishedDownloadingURL:(NSURL *)url toFile:(NSString *)fileName userInfo:(NSDictionary *)userInfo {
NSLog(#"finishedDownloadingURL =%#",url);
}
- (void)downloadController:(HCDownloadViewController *)vc failedDownloadingURL:(NSURL *)url withError:(NSError *)error userInfo:(NSDictionary *)userInfo {
NSLog(#"failedDownloadingURL=%#",url);
}
#pragma mark - File Functions - Document Functions
-(void)createDocumentDirectory:(NSString*)pStrDirectoryName
{
NSString *dataPath = [self getDocumentDirectoryPath:pStrDirectoryName];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:NULL];
}
-(NSString*)getDocumentDirectoryPath:(NSString*)pStrPathName
{
NSString *strPath = #"";
if(pStrPathName)
strPath = [[kAppDirectoryPath objectAtIndex:0] stringByAppendingPathComponent:pStrPathName];
return strPath;
}
Edit
another simple way is
ImageDownload
Related
It is fairly common to allow users to download a file via having some path modifier in the URL
//MVC Action to download the correct file From our Content directory
public ActionResult GetFile(string name) {
string path = this.Server.MapPath("~/Content/" + name);
byte[] file = System.IO.File.ReadAllBytes(path);
return this.File(file, "html/text");
}
quoted from http://hugoware.net/blog/dude-for-real-encrypt-your-web-config
An application I'm working with has liberal path downloads ( directory based ) sprinkled throughout the application, hence it is super vulnerable to requests like "http://localhost:1100/Home/GetFile?name=../web.config" or ( ..%2fweb.config )
Is there an easy way to restrict access to the config file - do I need to provide a custom Server.MapPath with whitelisted directories - or is there a better way.
How do you secure your file downloads - are path based downloads inherently insecure?
A simple option, assuming that all files in the ~/Content directory are safe to download would be to verify that the path is actually under (or in) the ~/Content directory and not up from it, as ~/Content/../web.config would be. I might do something like this:
// MVC Action to download the correct file From our Content directory
public ActionResult GetFile(string name) {
// Safe path
var safePath = this.Server.MapPath("~/Content");
// Requested path
string path = this.Server.MapPath("~/Content/" + name);
// Make sure requested path is safe
if (!path.StartsWith(safePath))
// NOT SAFE! Do something here, like show an error message
// Read file and return it
byte[] file = System.IO.File.ReadAllBytes(path);
return this.File(file, "html/text");
}
Is it possible to save an image from an url in the assets folder?
void DataPacking::createAndSaveImage(QString argSavingFilePath,
QByteArray argDataLoaded) {
m_file = new QFile;
m_file->setFileName(argSavingFilePath);
m_file->open(QIODevice::WriteOnly);
m_file->write(argDataLoaded);
m_file->close();
m_file->~QFile();
}
m_savingFilePath = QDir::homePath() + "app/native/assets/images/"
+ QString("multipleActive.png");
createAndSaveImage(m_savingFilePath, m_dataLoaded);
but when I try to use this image, I am getting the error below.
"Unable to get asset in (/apps/com.bluewave.LeasePlan.testDev_e_LeasePlan45b0f435/native/assets/): (/images/multipleActive.png)."
The assets directory (or more properly the app directory) is part of the protected area of the application sandbox that can not be changed. If you want to store data in the sandbox you should use the data directory.
See: https://developer.blackberry.com/native/documentation/cascades/device_platform/data_access/file_system.html
I've an existing SQLite database called data_items.sqlite. This database includes about 10 tables and some initial data which I would like to import into XCode to open the database with the Phonegap Plugin in this way:
function onDeviceReady() {
var db = window.sqlitePlugin.openDatabase("data_items.sqlite", "1.0", "PhoneGap Demo", 200000);
...
}
How can I import the datafile? Where do I have to copy the file?
First create database as u used name data_items.sqlite and remove .sqlite extension. Then drag this db at Resources directory in xCode and follow next .
Choose option for adding file box will appear
check checkbox says 'Copy items into destination group's folder (if needed)' and finish.
You will see the Database file as sub list of Resources Directory
Sorry I don't have enough reputation to post images here
Now follow the link to copy this database file into location
How to copy sqlite database when application is launched in iOS?
I used the following code before the #end at last line in AppDelegate.m
- (void) copyDatabaseIfNeeded{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
_dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:_dbPath];
if(!success){
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"data_items"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:_dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}}
/********* Database Path *********/
- (NSString *) getDBPath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"data_items"];
}
And Copy the line
[self copyDatabaseIfNeeded];
after the code
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
That's it. Use your code
function onDeviceReady() {
var db = window.sqlitePlugin.openDatabase("data_items", "1.0", "data_items", 200000);
...
}
You can also edit database directly in from the copied location. Use following link
Where does the iPhone Simulator store its data?
It appears not to be possible to access the assets folder from PhoneGap, so you have to write a native plugin to copy the database file:
Prepopulate SQLite DataBase in PhoneGap Application
I've been working on this problem for a week, and I googled and searched stack overflow, read about 40 posts, still can't fix my problem. here is what i did:
1.I wrote a testing app to create the sqlite database, and preload it with data.
2.I create myApp, and copied the preloaded DB to resource folder.
3.I wrote the following code to get the DB:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (!self.myDataBase) {
NSURL *url = [self localDocumentsDirectoryURL];
url = [url URLByAppendingPathComponent:#"myDB/"];
self.myDataBase = [[UIManagedDocument alloc] initWithFileURL:url];
}
return YES;
}
-(NSURL*)localDocumentsDirectoryURL {
static NSURL *localDocumentsDirectoryURL = nil;
if (localDocumentsDirectoryURL == nil) {
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,NSUserDomainMask, YES ) objectAtIndex:0];
localDocumentsDirectoryURL = [NSURL fileURLWithPath:documentsDirectoryPath];
}
return localDocumentsDirectoryURL;
}
- (void)useDocument
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.ICCarDataBase.fileURL path]])
{
[self.ICCarDataBase saveToURL:self.ICCarDataBase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {}];
}
else
{
[self.ICCarDataBase openWithCompletionHandler:^(BOOL success) {}];
}
}
- (void) setICCarDataBase:(UIManagedDocument *)carDataBase
{
if (_ICCarDataBase != carDataBase) {
_ICCarDataBase = carDataBase;
[self useDocument];
}
}
Then when I run myApp in Simulator, myApp successfully get the DB data, and when I run it in my iPhone, the myApp can't get the DB data.
I don't know if the SDK version matters, coz, the simulator is iphone 5.1, and my iPhone is 5.0 (jailbreak). And I don't use any 5.1 specific function in my App.
Some says that you should copy the DataBase to document dir first for it to work, I've tried the solution, still works ok in simulator, but no data in iPhone. Plus, I looked into iphone folders using iTool, myDB folder is already in the document dir.The post suggest the solution is here:Pre-load core data database in iOS 5 with UIManagedDocument
Other says I should use persistentStoreCoordinator directly. But I think UIManagedDocument could work in my situation, since it create a implicit persistentStoreCoordinator itself.
Any suggestion about what's wrong with myApp?
And anyone can tell me why ios wrap the sqlite DB with two layers of folders, and name the actual sqlite db persisentStore?
I've solved this problem, thanks to this postiPhone: Can access files in documents directory in Simulator, but not device
In this post he referenced this blog :Xcode resource groups and folder references when building for iPhone
After solving my problem, I've come to realize the reason that preload sqlite database won't work in device is: when Xcode copy database to the device from the bundle, the folder layers(myDB/StoreContent/persistentStore) wrapping the persistentStore is removed. So there is only a persistentStore file mixed with all other files in the device in the myApp.app bundle. And when you use UIManagedDocument to access sqlite database, it can only work with sqlite in such directory structure: myDB/StoreContent/persistentStore. So, with only a naked persistentStore file, the UIManagedDocument will create a whole new directory structure for you, with an empty persistentStore in it.
If someone can suggest a way for UIManagedDocument to work with the persistentStore file without folder layers, I would be interested.
And I use this code to access the DB after I successfully replicate the directory structure in my device bundle:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (!self.myDataBase) {
NSURL *url = [[NSBundle mainBundle] resourceURL];
url = [url URLByAppendingPathComponent:#"myDB/"];
self.myDataBase = [[UIManagedDocument alloc] initWithFileURL:url];
}
return YES;
}
I'll ONLY recieve an "Error #3000: Illegal path name" if I try to open a file which is placed inside the app-folder of the air. If the file is somewhere else outside of the app-folder it works.
private var file:File = File.documentsDirectory;
public function download():void{
var pdfFilter:FileFilter = new FileFilter("PDF Files", "*.pdf");
file.browseForOpen("Open", [pdfFilter]);
file.addEventListener(Event.SELECT, fileSelected);
}
private function fileSelected(e:Event):void
{
var destination:File = File.applicationDirectory
destination = destination.resolvePath("test.pdf");
/*
//This works, also if the file to copy is placed inside the appfolder
file.copyTo(destination, true);
*/
/*This Throws me an Error #3000, but ONLY if the file is located in
the App folder*/
file.openWithDefaultApplication();
}
When i try to get the same file and copy it to another place it's doing fine.
Why that? Something special to do if i wanna open files which are inside the appfolder?
It also don't work in debug mode - bin-debug.
Regards, Temo
After reading the document a few times i saw that this is not possible (it's not a bug, it's a feature!?!)
Opening files with the default system application
You cannot use the openWithDefaultApplication() method with files located in the application directory.
So I do this instead:
file.copyTo(tempFile);
tempFile.openWithDefaultApplication();
Not so nice, but it works.