downloadIpc.ts 2.6 KB
Newer Older
S
Sandeep Somavarapu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { URI } from 'vs/base/common/uri';
import * as path from 'path';
import * as fs from 'fs';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event, Emitter, buffer } from 'vs/base/common/event';
import { IDownloadService } from 'vs/platform/download/common/download';
import { mkdirp } from 'vs/base/node/pfs';
import { IURITransformer } from 'vs/base/common/uriIpc';

export type UploadResponse = Buffer | string | undefined;

export function upload(uri: URI): Event<UploadResponse> {
	const stream = new Emitter<UploadResponse>();
	const readstream = fs.createReadStream(uri.fsPath);
	readstream.on('data', data => stream.fire(data));
	readstream.on('error', error => stream.fire(error.toString()));
	readstream.on('close', () => stream.fire());
	return stream.event;
}

export interface IDownloadServiceChannel extends IChannel {
	listen(event: 'upload', uri: URI): Event<UploadResponse>;
	listen(event: string, arg?: any): Event<any>;
}

export class DownloadServiceChannel implements IDownloadServiceChannel {

	constructor() { }

	listen(event: string, arg?: any): Event<any> {
		switch (event) {
			case 'upload': return buffer(upload(URI.revive(arg)));
		}
		return undefined;
	}

	call(command: string, arg?: any): TPromise<any> {
		throw new Error('No calls');
	}
}

export class DownloadServiceChannelClient implements IDownloadService {

	_serviceBrand: any;

	constructor(private channel: IDownloadServiceChannel, private uriTransformer: IURITransformer) { }

	download(from: URI, to: string): Promise<void> {
		from = this.uriTransformer.transformOutgoing(from);
		const dirName = path.dirname(to);
		let out: fs.WriteStream;
		return new Promise((c, e) => {
			return mkdirp(dirName)
				.then(() => {
					out = fs.createWriteStream(to);
					out.once('close', () => c(null));
					out.once('error', e);
					const uploadStream = this.channel.listen('upload', from);
					const disposable = uploadStream((result: UploadResponse) => {
						if (result === void 0) {
							disposable.dispose();
							out.end(c);
						} else if (Buffer.isBuffer(result)) {
							out.write(result);
						} else if (typeof result === 'string') {
							disposable.dispose();
							out.end(() => e(result));
						}
					});
				});
		});
	}
}