file download is implemented
This commit is contained in:
parent
958295a8c1
commit
88e715eb60
|
@ -2,12 +2,15 @@ import { app, ipcMain, IpcMainEvent, remote } from 'electron';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import * as fse from 'fs-extra';
|
import * as fse from 'fs-extra';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
import { AppWindow } from './app/AppWindow';
|
import { AppWindow } from './app/AppWindow';
|
||||||
import { now } from './util/now';
|
import { now } from './util/now';
|
||||||
import { showUncaughtException } from './crash/show-uncaught-exception';
|
import { showUncaughtException } from './crash/show-uncaught-exception';
|
||||||
import { Channel } from '@ucap-webmessenger/native-electron';
|
import { Channel } from '@ucap-webmessenger/native-electron';
|
||||||
import { root } from './util/root';
|
import { root } from './util/root';
|
||||||
|
import { DefaultFolder } from './lib/default-folder';
|
||||||
|
import { FileUtil } from './lib/file-util';
|
||||||
|
|
||||||
let appWindow: AppWindow | null = null;
|
let appWindow: AppWindow | null = null;
|
||||||
|
|
||||||
|
@ -179,19 +182,37 @@ ipcMain.on(Channel.checkForUpdates, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
|
|
||||||
ipcMain.on(Channel.readFile, (event: IpcMainEvent, ...args: any[]) => {
|
ipcMain.on(Channel.readFile, (event: IpcMainEvent, ...args: any[]) => {
|
||||||
try {
|
try {
|
||||||
const rBuf = fse.readFileSync(root(args[0]));
|
fse.readFile(root(args[0]), (err, data) => {
|
||||||
event.returnValue = rBuf.buffer;
|
if (!!err) {
|
||||||
|
event.returnValue = null;
|
||||||
|
} else {
|
||||||
|
event.returnValue = new Blob([data]);
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
event.returnValue = null;
|
event.returnValue = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Channel.saveFile, (event: IpcMainEvent, ...args: any[]) => {
|
ipcMain.on(Channel.saveFile, async (event: IpcMainEvent, ...args: any[]) => {
|
||||||
try {
|
try {
|
||||||
fse.writeFileSync(root(args[0]), args[1]);
|
const buffer: Buffer = args[0];
|
||||||
event.returnValue = true;
|
const fileName: string = args[1];
|
||||||
|
let savePath: string = path.join(
|
||||||
|
!!args[2] ? args[2] : DefaultFolder.downloads(),
|
||||||
|
fileName
|
||||||
|
);
|
||||||
|
savePath = await FileUtil.uniqueFileName(savePath);
|
||||||
|
|
||||||
|
fse.writeFile(savePath, buffer, err => {
|
||||||
|
if (!err) {
|
||||||
|
event.returnValue = savePath;
|
||||||
|
} else {
|
||||||
|
event.returnValue = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
event.returnValue = false;
|
event.returnValue = undefined;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
37
main/src/lib/default-folder.ts
Normal file
37
main/src/lib/default-folder.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import * as os from 'os';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
import * as fse from 'fs-extra';
|
||||||
|
|
||||||
|
export class DefaultFolder {
|
||||||
|
static downloads(): string {
|
||||||
|
switch (os.platform()) {
|
||||||
|
case 'win32':
|
||||||
|
return `${process.env.USERPROFILE}/Downloads`;
|
||||||
|
case 'darwin':
|
||||||
|
return `${process.env.HOME}/Downloads`;
|
||||||
|
case 'linux': {
|
||||||
|
let dir: Buffer;
|
||||||
|
try {
|
||||||
|
dir = execSync('xdg-user-dir DOWNLOAD', { stdio: [0, 3, 3] });
|
||||||
|
} catch (_) {}
|
||||||
|
|
||||||
|
if (dir) {
|
||||||
|
return dir.toString('utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
let stat: fse.Stats;
|
||||||
|
const homeDownloads = `${process.env.HOME}/Downloads`;
|
||||||
|
try {
|
||||||
|
stat = fse.statSync(homeDownloads);
|
||||||
|
} catch (_) {}
|
||||||
|
if (stat) {
|
||||||
|
return homeDownloads;
|
||||||
|
}
|
||||||
|
return '/tmp/';
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
222
main/src/lib/file-util.ts
Normal file
222
main/src/lib/file-util.ts
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as fse from 'fs-extra';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* separator
|
||||||
|
* If the specified filename exists, the separator will be added before the incremental value such as: file{separator}2.jpg
|
||||||
|
* The default value is '-'.
|
||||||
|
*
|
||||||
|
* mode
|
||||||
|
* The mode allows you to specify which characters to use to generate the incremental value (the string after the separator)
|
||||||
|
* The default value is 'numeric'.
|
||||||
|
* 'numeric' Using the following characters: 1234567890
|
||||||
|
* 'alpha' Using the following characters: abcdefghijklmnopqrstuvwxyz
|
||||||
|
* 'ALPHA' Using the following characters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||||
|
* 'alphanumeric' Using the following characters: 0123456789abcdefghijklmnopqrstuvwxyz
|
||||||
|
* 'ALPHANUMERIC' Using the following characters: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||||
|
* 'charset' You must specify the characters you wish to use in the charset option
|
||||||
|
*
|
||||||
|
* paddingCharacter && paddingSize
|
||||||
|
* If you wish to left-pad the incremental values with a character, use this option. Here's an example :
|
||||||
|
* var uniquefilename = require('uniquefilename');
|
||||||
|
* options = {mode: 'alpha', paddingCharacter: '0', paddingSize: 3};
|
||||||
|
* uniquefilename.get('/path/to/dir/file.jpg', options, function(filename) {
|
||||||
|
* // filename might be "/path/to/dir/file.jpg",
|
||||||
|
* // "/path/to/dir/file-002.jpg", "/path/to/dir/file-045.jpg", etc...
|
||||||
|
* // depending on the files that exist on your filesystem
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* alwaysAppend
|
||||||
|
* If alwaysAppend is true filenames will include the separator and attachment from the first request.
|
||||||
|
* So instead of file.jpg, file-2.jpg you'd get file-1.jpg, file-2.jpg.
|
||||||
|
*/
|
||||||
|
export interface UniqueFileNameOption {
|
||||||
|
separator?: string;
|
||||||
|
mode?:
|
||||||
|
| 'numeric'
|
||||||
|
| 'alpha'
|
||||||
|
| 'ALPHA'
|
||||||
|
| 'alphanumeric'
|
||||||
|
| 'ALPHANUMERIC'
|
||||||
|
| 'charset';
|
||||||
|
paddingCharacter?: string;
|
||||||
|
paddingSize?: number;
|
||||||
|
alwaysAppend?: boolean;
|
||||||
|
charset?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const charsets = {
|
||||||
|
alpha: 'abcdefghijklmnopqrstuvwxyz',
|
||||||
|
alphanumeric: '0123456789abcdefghijklmnopqrstuvwxyz',
|
||||||
|
ALPHA: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||||
|
ALPHANUMERIC: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||||
|
};
|
||||||
|
|
||||||
|
interface UniqueFile {
|
||||||
|
dir?: string;
|
||||||
|
ext?: string;
|
||||||
|
base?: string;
|
||||||
|
increment?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FileUtil {
|
||||||
|
static blobToBuffer(blob: Blob): Promise<Buffer> {
|
||||||
|
if (typeof Blob === 'undefined' || !(blob instanceof Blob)) {
|
||||||
|
throw new Error('first argument must be a Blob');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise<Buffer>((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => {
|
||||||
|
resolve(Buffer.from(reader.result as ArrayBuffer));
|
||||||
|
};
|
||||||
|
reader.onerror = () => {
|
||||||
|
reader.abort();
|
||||||
|
reject(reader.error);
|
||||||
|
};
|
||||||
|
reader.readAsArrayBuffer(blob);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static uniqueFileName(
|
||||||
|
filePath: string,
|
||||||
|
options?: UniqueFileNameOption
|
||||||
|
): Promise<string> {
|
||||||
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
const dir = path.dirname(filePath);
|
||||||
|
const ext = path.extname(filePath);
|
||||||
|
const base = path.basename(filePath, ext);
|
||||||
|
|
||||||
|
const uniqueFile: UniqueFile = {
|
||||||
|
dir,
|
||||||
|
ext,
|
||||||
|
base
|
||||||
|
};
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
options.separator = options.separator || '-';
|
||||||
|
options.mode = options.mode || 'numeric';
|
||||||
|
|
||||||
|
if ('numeric' !== options.mode) {
|
||||||
|
if (charsets[options.mode]) {
|
||||||
|
options.charset = charsets[options.mode];
|
||||||
|
options.mode = 'charset';
|
||||||
|
} else if (
|
||||||
|
'charset' !== options.mode ||
|
||||||
|
('charset' === options.mode && !options.charset)
|
||||||
|
) {
|
||||||
|
options.mode = 'numeric';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.paddingSize && !options.paddingCharacter) {
|
||||||
|
options.paddingCharacter = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
FileUtil.uniqueFileNameProcess(
|
||||||
|
uniqueFile,
|
||||||
|
options,
|
||||||
|
(fileName: string) => {
|
||||||
|
resolve(fileName);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uniqueFileNameProcess(
|
||||||
|
uniqueFile: UniqueFile,
|
||||||
|
options: UniqueFileNameOption,
|
||||||
|
callback: (fileName: string) => void
|
||||||
|
) {
|
||||||
|
let fileName: string;
|
||||||
|
let append = '';
|
||||||
|
|
||||||
|
if (options.alwaysAppend && !uniqueFile.increment) {
|
||||||
|
uniqueFile.increment = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uniqueFile.increment) {
|
||||||
|
if ('numeric' === options.mode) {
|
||||||
|
append = '' + uniqueFile.increment;
|
||||||
|
} else {
|
||||||
|
append = FileUtil.numberToString(uniqueFile.increment, options.charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.paddingSize) {
|
||||||
|
while (append.length < options.paddingSize) {
|
||||||
|
append = options.paddingCharacter + append;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
append = options.separator + append;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName = path.join(
|
||||||
|
uniqueFile.dir,
|
||||||
|
uniqueFile.base + append + uniqueFile.ext
|
||||||
|
);
|
||||||
|
if (fse.existsSync(fileName)) {
|
||||||
|
if (uniqueFile.increment) {
|
||||||
|
uniqueFile.increment += 1;
|
||||||
|
} else {
|
||||||
|
uniqueFile.increment = 'numeric' === options.mode ? 2 : 1;
|
||||||
|
}
|
||||||
|
return FileUtil.uniqueFileNameProcess(uniqueFile, options, callback);
|
||||||
|
} else {
|
||||||
|
return callback(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static numberToString(nbr: number, charset: string) {
|
||||||
|
const charsetLen = charset.length;
|
||||||
|
let strLen = 0;
|
||||||
|
let strThisLen = 0;
|
||||||
|
let tmp: number;
|
||||||
|
|
||||||
|
for (let maxpower = 20; maxpower >= 0; maxpower--) {
|
||||||
|
const maxvalue = FileUtil.sumOfPowerFromOne(charsetLen, maxpower);
|
||||||
|
|
||||||
|
if (maxvalue < nbr) {
|
||||||
|
strLen = maxpower + 1;
|
||||||
|
strThisLen = maxvalue + Math.pow(charsetLen, maxpower + 1) - maxvalue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === strLen) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let str = '';
|
||||||
|
while (--strLen >= 0) {
|
||||||
|
if (strLen === 0) {
|
||||||
|
str += charset.charAt(nbr - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
strThisLen = Math.pow(charsetLen, strLen);
|
||||||
|
const initial = FileUtil.sumOfPowerFromOne(charsetLen, strLen - 1);
|
||||||
|
|
||||||
|
for (tmp = charsetLen; tmp >= 1; tmp--) {
|
||||||
|
if (initial + tmp * strThisLen < nbr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nbr -= tmp * strThisLen;
|
||||||
|
str += charset.charAt(tmp - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static sumOfPowerFromOne(base: number, maxpower: number) {
|
||||||
|
let value = 0;
|
||||||
|
for (let tmp = maxpower; tmp >= 1; tmp--) {
|
||||||
|
value += Math.pow(base, tmp);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,8 +9,10 @@ import {
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { FileEventJson } from '@ucap-webmessenger/protocol-event';
|
import { FileEventJson } from '@ucap-webmessenger/protocol-event';
|
||||||
import { DeviceType } from '@ucap-webmessenger/core';
|
import { DeviceType, FileUtil } from '@ucap-webmessenger/core';
|
||||||
import * as FileSaver from 'file-saver';
|
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
||||||
|
import { take } from 'rxjs/operators';
|
||||||
|
import { SnackBarService } from '@ucap-webmessenger/ui';
|
||||||
|
|
||||||
export interface FileViewerDialogData {
|
export interface FileViewerDialogData {
|
||||||
fileInfo: FileEventJson;
|
fileInfo: FileEventJson;
|
||||||
|
@ -40,6 +42,8 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
FileViewerDialogResult
|
FileViewerDialogResult
|
||||||
>,
|
>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: FileViewerDialogData,
|
@Inject(MAT_DIALOG_DATA) public data: FileViewerDialogData,
|
||||||
|
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
||||||
|
private snackBarService: SnackBarService,
|
||||||
private logger: NGXLogger
|
private logger: NGXLogger
|
||||||
) {
|
) {
|
||||||
this.fileInfo = data.fileInfo;
|
this.fileInfo = data.fileInfo;
|
||||||
|
@ -54,7 +58,29 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
||||||
ngOnDestroy(): void {}
|
ngOnDestroy(): void {}
|
||||||
|
|
||||||
onDownload(blob: Blob): void {
|
onDownload(blob: Blob): void {
|
||||||
FileSaver.saveAs(blob, this.fileInfo.fileName);
|
FileUtil.fromBlobToBuffer(blob)
|
||||||
|
.then(buffer => {
|
||||||
|
this.nativeService
|
||||||
|
.saveFile(buffer, this.fileInfo.fileName)
|
||||||
|
.pipe(take(1))
|
||||||
|
.subscribe(result => {
|
||||||
|
if (!!result) {
|
||||||
|
this.snackBarService.open(
|
||||||
|
`파일이 경로[${result}]에 저장되었습니다.`,
|
||||||
|
'',
|
||||||
|
{
|
||||||
|
duration: 3000,
|
||||||
|
verticalPosition: 'bottom'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.snackBarService.open('파일 저장에 실패하였습니다.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(reason => {
|
||||||
|
this.logger.error('download', reason);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onClosedViewer(): void {
|
onClosedViewer(): void {
|
||||||
|
|
|
@ -14,11 +14,9 @@ export class FileUtil {
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
static toDataUrl(blob: Blob): Promise<string | ArrayBuffer> {
|
static fromBlobToDataUrl(blob: Blob): Promise<string | ArrayBuffer> {
|
||||||
return new Promise<string | ArrayBuffer>((resolve, reject) => {
|
return new Promise<string | ArrayBuffer>((resolve, reject) => {
|
||||||
const fileReader = new FileReader();
|
const fileReader = new FileReader();
|
||||||
fileReader.readAsDataURL(blob);
|
|
||||||
|
|
||||||
fileReader.onload = () => {
|
fileReader.onload = () => {
|
||||||
return resolve(fileReader.result);
|
return resolve(fileReader.result);
|
||||||
};
|
};
|
||||||
|
@ -26,6 +24,35 @@ export class FileUtil {
|
||||||
fileReader.abort();
|
fileReader.abort();
|
||||||
return reject(fileReader.error);
|
return reject(fileReader.error);
|
||||||
};
|
};
|
||||||
|
fileReader.readAsDataURL(blob);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromBlobToBuffer(blob: Blob): Promise<Buffer> {
|
||||||
|
return new Promise<Buffer>((resolve, reject) => {
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = () => {
|
||||||
|
return resolve(Buffer.from(fileReader.result as ArrayBuffer));
|
||||||
|
};
|
||||||
|
fileReader.onerror = (event: ProgressEvent) => {
|
||||||
|
fileReader.abort();
|
||||||
|
return reject(fileReader.error);
|
||||||
|
};
|
||||||
|
fileReader.readAsArrayBuffer(blob);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromBlobToString(blob: Blob): Promise<string> {
|
||||||
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = () => {
|
||||||
|
return resolve(fileReader.result.toString());
|
||||||
|
};
|
||||||
|
fileReader.onerror = (event: ProgressEvent) => {
|
||||||
|
fileReader.abort();
|
||||||
|
return reject(fileReader.error);
|
||||||
|
};
|
||||||
|
fileReader.readAsArrayBuffer(blob);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,20 @@ export class BrowserNativeService implements NativeService {
|
||||||
|
|
||||||
showImageViewer(): void {}
|
showImageViewer(): void {}
|
||||||
|
|
||||||
readFile(path: string): Observable<ArrayBuffer> {
|
readFile(path: string): Observable<Buffer> {
|
||||||
return this.httpClient.get(path, { responseType: 'arraybuffer' });
|
return this.httpClient.get(path, { responseType: 'arraybuffer' }).pipe(
|
||||||
|
map(arrayBuffer => {
|
||||||
|
return Buffer.from(arrayBuffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile(path: string, buf: ArrayBuffer): Observable<boolean> {
|
saveFile(
|
||||||
return this.httpClient.post<boolean>(path, buf, {});
|
buffer: Buffer,
|
||||||
|
fileName: string,
|
||||||
|
path?: string
|
||||||
|
): Observable<string> {
|
||||||
|
return this.httpClient.post<string>(path, buffer, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
windowStateChanged(): Observable<WindowState> {
|
windowStateChanged(): Observable<WindowState> {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { TranslateLoader } from '@ngx-translate/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { NativeService } from '@ucap-webmessenger/native';
|
import { NativeService } from '@ucap-webmessenger/native';
|
||||||
import { take, map } from 'rxjs/operators';
|
import { take, map } from 'rxjs/operators';
|
||||||
|
import { FileUtil } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
export class TranslateBrowserLoader implements TranslateLoader {
|
export class TranslateBrowserLoader implements TranslateLoader {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -18,8 +19,8 @@ export class TranslateBrowserLoader implements TranslateLoader {
|
||||||
.readFile(`${this.prefix}${lang}.${this.suffix}`)
|
.readFile(`${this.prefix}${lang}.${this.suffix}`)
|
||||||
.pipe(
|
.pipe(
|
||||||
take(1),
|
take(1),
|
||||||
map(buf => {
|
map(buffer => {
|
||||||
return JSON.parse(Buffer.from(buf).toString('utf8'));
|
return JSON.parse(buffer.toString('utf-8'));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,8 @@ export class ElectronNativeService implements NativeService {
|
||||||
ipcRenderer.send(Channel.showImageViewer);
|
ipcRenderer.send(Channel.showImageViewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
readFile(path: string): Observable<ArrayBuffer> {
|
readFile(path: string): Observable<Buffer> {
|
||||||
return new Observable<ArrayBuffer>(subscriber => {
|
return new Observable<Buffer>(subscriber => {
|
||||||
try {
|
try {
|
||||||
subscriber.next(ipcRenderer.sendSync(Channel.readFile, path));
|
subscriber.next(ipcRenderer.sendSync(Channel.readFile, path));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -54,10 +54,16 @@ export class ElectronNativeService implements NativeService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile(path: string, buf: ArrayBuffer): Observable<boolean> {
|
saveFile(
|
||||||
return new Observable<boolean>(subscriber => {
|
buffer: Buffer,
|
||||||
|
fileName: string,
|
||||||
|
path?: string
|
||||||
|
): Observable<string> {
|
||||||
|
return new Observable<string>(subscriber => {
|
||||||
try {
|
try {
|
||||||
subscriber.next(ipcRenderer.sendSync(Channel.saveFile, path, buf));
|
subscriber.next(
|
||||||
|
ipcRenderer.sendSync(Channel.saveFile, buffer, fileName, path)
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
subscriber.error(error);
|
subscriber.error(error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -9,8 +9,8 @@ export interface NativeService {
|
||||||
|
|
||||||
showImageViewer(): void;
|
showImageViewer(): void;
|
||||||
|
|
||||||
saveFile(path: string, buf: ArrayBuffer): Observable<boolean>;
|
saveFile(buffer: Buffer, fileName: string, path?: string): Observable<string>;
|
||||||
readFile(path: string): Observable<ArrayBuffer>;
|
readFile(path: string): Observable<Buffer>;
|
||||||
|
|
||||||
windowStateChanged(): Observable<WindowState>;
|
windowStateChanged(): Observable<WindowState>;
|
||||||
windowClose(): void;
|
windowClose(): void;
|
||||||
|
|
|
@ -69,7 +69,7 @@ export class ImageViewerComponent implements OnInit {
|
||||||
blob.size,
|
blob.size,
|
||||||
MimeUtil.getMimeFromExtension(this.fileInfo.fileExt)
|
MimeUtil.getMimeFromExtension(this.fileInfo.fileExt)
|
||||||
);
|
);
|
||||||
this.imageSrc = await FileUtil.toDataUrl(this.blob);
|
this.imageSrc = await FileUtil.fromBlobToDataUrl(this.blob);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user