Skip to content

Commit a9ec255

Browse files
authored
Merge pull request #2 from nstudio/feature/image-saving
feat(ios): image save to disk option
2 parents dd1be42 + 586d3dc commit a9ec255

File tree

5 files changed

+134
-15
lines changed

5 files changed

+134
-15
lines changed

src/angular/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NgModule, ModuleWithProviders, Optional, SkipSelf } from '@angular/core';
22
import { TNSBrowserXhr } from './TNSBrowserXhr';
33
import { XhrFactory } from '@angular/common/http';
4-
import { TNSHttpDebugging } from '../http/http-request-common';
4+
import { TNSHttpSettings, ISaveImageSettings } from '../http/http-request-common';
55

66
const BASE_PROVIDERS = [
77
TNSBrowserXhr,
@@ -12,9 +12,12 @@ const BASE_PROVIDERS = [
1212
providers: BASE_PROVIDERS
1313
})
1414
export class NativeScriptHttpAsyncModule {
15-
static forRoot(options: { configuredProviders?: Array<any>; debug?: boolean; }): ModuleWithProviders {
15+
static forRoot(options: { configuredProviders?: Array<any>; debug?: boolean; saveImageSettings?: ISaveImageSettings }): ModuleWithProviders {
1616
if (options.debug) {
17-
TNSHttpDebugging.enabled = true;
17+
TNSHttpSettings.debug = true;
18+
}
19+
if (options.saveImageSettings) {
20+
TNSHttpSettings.saveImage = options.saveImageSettings;
1821
}
1922
return {
2023
ngModule: NativeScriptHttpAsyncModule,

src/file/file.android.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ export class FileManager {
3535
}
3636
}));
3737
}
38+
39+
public static deleteFile(path: string, options: Options = {asStream: false}, callback: (...args) => void) {
40+
// TODO
41+
callback(null, true);
42+
}
3843
}
3944

4045
export interface Options {

src/file/file.ios.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ export class FileManager {
2727
}
2828
});
2929
}
30+
31+
public static deleteFile(path: string, options: Options = {asStream: false}, callback: (...args) => void) {
32+
dispatch_async(background_queue, () => {
33+
try {
34+
NSFileManager.defaultManager.removeItemAtPathError(path);
35+
callback(null, true);
36+
} catch (e) {
37+
callback(e, false);
38+
}
39+
});
40+
}
3041
}
3142

3243
export interface Options {

src/http/http-request-common.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,33 @@
1-
export class TNSHttpDebugging {
2-
static enabled: boolean;
3-
// TODO: could add other debuggin options
1+
export interface ISaveImageSettings {
2+
numberOfRequests?: number;
3+
removeAfterDays?: number;
4+
storageKey?: string;
45
}
56

7+
export const SaveImageStorageKey = 'http.saved-images';
8+
export function isImageUrl(url: string) {
9+
return url && /(http(s?):)([/|.|\w|\s|-])*\.(?:jpg|gif|png)/ig.test(url);
10+
}
11+
export function fileNameFromPath(fullPath: string) {
12+
let filename = '';
13+
if (fullPath) {
14+
filename = fullPath.replace(/^.*[\\\/]/ig, '');
15+
}
16+
return filename;
17+
}
18+
19+
export class TNSHttpSettings {
20+
static debug: boolean;
21+
static saveImage: ISaveImageSettings;
22+
static currentlySavedImages: { [url: string]: {
23+
date: number;
24+
requests: number;
25+
localPath?: string;
26+
}
27+
};
28+
}
29+
30+
631
export class ProgressEvent {
732
private _type: string;
833
private _lengthComputable: boolean;

src/http/http.ios.ts

Lines changed: 84 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import * as types from 'tns-core-modules/utils/types';
2-
import { Headers, HttpError, HttpRequestOptions, TNSHttpDebugging } from './http-request-common';
2+
import { File, knownFolders, path } from 'tns-core-modules/file-system';
3+
import { FileManager } from '../file/file';
4+
import { Headers, HttpError, HttpRequestOptions, TNSHttpSettings, SaveImageStorageKey, isImageUrl, fileNameFromPath } from './http-request-common';
5+
import { getString, setString } from 'tns-core-modules/application-settings';
36

47
export type CancellablePromise = Promise<any> & { cancel: () => void };
58

@@ -302,6 +305,16 @@ class NSURLSessionTaskDelegateImpl extends NSObject
302305
} else {
303306
content = this._data;
304307
}
308+
if (TNSHttpSettings.saveImage && TNSHttpSettings.currentlySavedImages && TNSHttpSettings.currentlySavedImages[this._url]) {
309+
// ensure saved to disk
310+
if (TNSHttpSettings.currentlySavedImages[this._url].localPath) {
311+
FileManager.writeFile(content, TNSHttpSettings.currentlySavedImages[this._url].localPath, function(error, result) {
312+
if (TNSHttpSettings.debug) {
313+
console.log('http image save:', error ? error : result);
314+
}
315+
});
316+
}
317+
}
305318

306319
if (this._debuggerRequest) {
307320
this._debuggerRequest.mimeType = this._response.MIMEType;
@@ -377,14 +390,8 @@ export class Http {
377390

378391
try {
379392

380-
let domainDebugger;
381-
let debugRequest;
382-
if (TNSHttpDebugging.enabled) {
383-
domainDebugger = require('tns-core-modules/debugger');
384-
const network = domainDebugger.getNetwork();
385-
debugRequest = network && network.create();
386-
}
387-
393+
const makeRemoteRequest = () => {
394+
// make remote request
388395
const urlRequest = NSMutableURLRequest.requestWithURL(
389396
NSURL.URLWithString(options.url)
390397
);
@@ -455,6 +462,74 @@ export class Http {
455462
debugRequest.requestWillBeSent(request);
456463
}
457464
task.resume();
465+
};
466+
467+
let domainDebugger;
468+
let debugRequest;
469+
if (TNSHttpSettings.debug) {
470+
domainDebugger = require('tns-core-modules/debugger');
471+
const network = domainDebugger.getNetwork();
472+
debugRequest = network && network.create();
473+
}
474+
475+
if (TNSHttpSettings.saveImage && isImageUrl(options.url)) {
476+
// handle saved images to disk
477+
if (!TNSHttpSettings.currentlySavedImages) {
478+
const stored = getString(SaveImageStorageKey);
479+
if (stored) {
480+
try {
481+
TNSHttpSettings.currentlySavedImages = JSON.parse(stored);
482+
} catch (err) {
483+
TNSHttpSettings.currentlySavedImages = {};
484+
}
485+
} else {
486+
TNSHttpSettings.currentlySavedImages = {};
487+
}
488+
}
489+
490+
const imageSetting = TNSHttpSettings.currentlySavedImages[options.url];
491+
const requests = imageSetting ? imageSetting.requests : 0;
492+
let localPath: string;
493+
if (imageSetting && imageSetting.localPath && File.exists(imageSetting.localPath)) {
494+
// previously saved to disk
495+
resolve({
496+
url: options.url,
497+
responseText: '',
498+
statusCode: 200,
499+
content: File.fromPath(imageSetting.localPath).readSync(function(err) {
500+
if (TNSHttpSettings.debug) {
501+
console.log('http image load error:', err);
502+
}
503+
}),
504+
headers: {
505+
'Content-Type': 'arraybuffer'
506+
}
507+
});
508+
509+
} else if (requests >= TNSHttpSettings.saveImage.numberOfRequests) {
510+
// setup to write to disk when response finishes
511+
let filename = fileNameFromPath(options.url);
512+
if (filename.indexOf('?')) {
513+
// strip any params if were any
514+
filename = filename.split('?')[0];
515+
}
516+
localPath = path.join(knownFolders.documents().path, filename);
517+
makeRemoteRequest();
518+
}
519+
520+
// save settings
521+
TNSHttpSettings.currentlySavedImages[options.url] = {
522+
...(imageSetting || {}),
523+
date: Date.now(),
524+
requests: requests + 1,
525+
localPath
526+
};
527+
setString(SaveImageStorageKey, JSON.stringify(TNSHttpSettings.currentlySavedImages));
528+
529+
} else {
530+
makeRemoteRequest();
531+
}
532+
458533
} catch (ex) {
459534
reject({
460535
type: HttpError.Error,

0 commit comments

Comments
 (0)