-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GH-1905: Implemented the file download functionality.
Closes #1905. Signed-off-by: Akos Kitta <kittaakos@gmail.com>
- Loading branch information
Showing
19 changed files
with
779 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Theia - File Download | ||
|
||
Provides the file download contribution to the `Files` navigator. | ||
|
||
Supports single and multi file downloads. | ||
- Single files will be downloaded as is. | ||
- Folders will be downloaded az ZIP archives. | ||
- When downloading multiple files, each file should be contained in the same parent folder. Otherwise, the command contribution is disabled. | ||
|
||
### REST API | ||
|
||
- To download a single file or folder use the following endpoint: `GET /file-download/?uri=/encoded/file/uri/to/the/resource`. | ||
- Example: `curl -X GET http://localhost:3000/file-download/?uri=file:///Users/akos.kitta/git/theia/package.json`. | ||
|
||
- To download multiple files (from the same folder) use the `PUT /file-download/` endpoint with the `application/json` content type header and the following body format: | ||
```json | ||
{ | ||
"uri": [ | ||
"/encoded/file/uri/to/the/resource", | ||
"/another/encoded/file/file/uri/to/the/resource" | ||
] | ||
} | ||
``` | ||
``` | ||
curl -X PUT -H "Content-Type: application/json" -d '{ "uris": ["file:///Users/akos.kitta/git/theia/package.json", "file:///Users/akos.kitta/git/theia/README.md"] }' http://localhost:3000/file-download/ | ||
``` | ||
## License | ||
[Apache-2.0](https://github.com/theia-ide/theia/blob/master/LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"extends": "../../configs/base.tsconfig", | ||
"compilerOptions": { | ||
"rootDir": "src", | ||
"outDir": "lib" | ||
}, | ||
"include": [ | ||
"src" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
{ | ||
"name": "@theia/file-download", | ||
"version": "0.3.11", | ||
"description": "Theia - File Download Extension", | ||
"dependencies": { | ||
"@theia/core": "^0.3.11", | ||
"@theia/filesystem": "^0.3.11", | ||
"@theia/navigator": "^0.3.11", | ||
"@theia/workspace": "^0.3.11", | ||
"@types/body-parser": "^1.17.0", | ||
"@types/mime-types": "^2.1.0", | ||
"@types/rimraf": "^2.0.2", | ||
"@types/uuid": "^3.4.3", | ||
"body-parser": "^1.18.3", | ||
"http-status-codes": "^1.3.0", | ||
"mime-types": "^2.1.18", | ||
"rimraf": "^2.6.2", | ||
"uuid": "^3.2.1", | ||
"zip-dir": "^1.0.2" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"theiaExtensions": [ | ||
{ | ||
"frontend": "lib/browser/file-download-frontend-module", | ||
"backend": "lib/node/file-download-backend-module" | ||
} | ||
], | ||
"keywords": [ | ||
"theia-extension" | ||
], | ||
"license": "Apache-2.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/theia-ide/theia.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/theia-ide/theia/issues" | ||
}, | ||
"homepage": "https://github.com/theia-ide/theia", | ||
"files": [ | ||
"lib", | ||
"src" | ||
], | ||
"scripts": { | ||
"prepare": "yarn run clean && yarn run build", | ||
"clean": "theiaext clean", | ||
"build": "theiaext build", | ||
"watch": "theiaext watch", | ||
"test": "theiaext test", | ||
"docs": "theiaext docs" | ||
}, | ||
"devDependencies": { | ||
"@theia/ext-scripts": "^0.3.11" | ||
}, | ||
"nyc": { | ||
"extends": "../../configs/nyc.json" | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
packages/file-download/src/browser/file-download-command-contribution.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright (C) 2018 TypeFox and others. | ||
* | ||
* Licensed 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 | ||
*/ | ||
|
||
import { inject, injectable } from 'inversify'; | ||
import URI from '@theia/core/lib/common/uri'; | ||
import { notEmpty } from '@theia/core/lib/common/objects'; | ||
import { UriSelection } from '@theia/core/lib/common/selection'; | ||
import { SelectionService } from '@theia/core/lib/common/selection-service'; | ||
import { Command, CommandContribution, CommandRegistry } from '@theia/core/lib/common/command'; | ||
import { UriAwareCommandHandler, UriCommandHandler } from '@theia/core/lib/common/uri-command-handler'; | ||
import { FileDownloadService } from './file-download-service'; | ||
|
||
@injectable() | ||
export class FileDownloadCommandContribution implements CommandContribution { | ||
|
||
@inject(FileDownloadService) | ||
protected readonly downloadService: FileDownloadService; | ||
|
||
@inject(SelectionService) | ||
protected readonly selectionService: SelectionService; | ||
|
||
registerCommands(registry: CommandRegistry): void { | ||
const options = { | ||
multi: true, | ||
isValid: this.isValid.bind(this) | ||
}; | ||
const handler = new UriAwareCommandHandler<URI[]>(this.selectionService, this.downloadHandler(), options); | ||
registry.registerCommand(FileDownloadCommands.DOWNLOAD, handler); | ||
} | ||
|
||
protected downloadHandler(): UriCommandHandler<URI[]> { | ||
return { | ||
execute: uri => this.executeDownload(uri), | ||
isEnabled: (uri, args) => this.isDownloadEnabled(uri, args), | ||
isVisible: (uri, args) => this.isDownloadVisible(uri, args), | ||
}; | ||
} | ||
|
||
protected async executeDownload(uris: URI[]): Promise<void> { | ||
this.downloadService.download(uris); | ||
} | ||
|
||
// tslint:disable-next-line:no-any | ||
protected isDownloadEnabled(uri: Object | undefined, ...args: any[]): boolean { | ||
return this.getUris(uri).length > 0; | ||
} | ||
|
||
// tslint:disable-next-line:no-any | ||
protected isDownloadVisible(uri: Object | undefined, ...args: any[]): boolean { | ||
return this.isDownloadEnabled(uri, args); | ||
} | ||
|
||
protected isValid(uris: URI[]): boolean { | ||
if (uris.length === 0) { | ||
return false; | ||
} | ||
if (uris.length === 1) { | ||
return true; | ||
} | ||
// Can download multiple files iff they are from the same container folder. | ||
const [firstUri, ...restUris] = uris; | ||
const expectedParent = firstUri.parent.toString(); | ||
return restUris.every(u => u.parent.toString() === expectedParent); | ||
} | ||
|
||
protected getUris(uri: Object | undefined): URI[] { | ||
if (uri === undefined) { | ||
return []; | ||
} | ||
return (Array.isArray(uri) ? uri : [uri]).map(u => this.getUri(u)).filter(notEmpty); | ||
} | ||
|
||
protected getUri(uri: Object | undefined): URI | undefined { | ||
if (uri instanceof URI) { | ||
return uri; | ||
} | ||
if (UriSelection.is(uri)) { | ||
return uri.uri; | ||
} | ||
return undefined; | ||
} | ||
|
||
} | ||
|
||
export namespace FileDownloadCommands { | ||
|
||
export const DOWNLOAD: Command = { | ||
id: 'file.download' | ||
}; | ||
|
||
} |
19 changes: 19 additions & 0 deletions
19
packages/file-download/src/browser/file-download-frontend-module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright (C) 2018 TypeFox and others. | ||
* | ||
* Licensed 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 | ||
*/ | ||
|
||
import { ContainerModule } from 'inversify'; | ||
import { MenuContribution } from '@theia/core/lib/common/menu'; | ||
import { CommandContribution } from '@theia/core/lib/common/command'; | ||
import { FileDownloadService } from './file-download-service'; | ||
import { FileDownloadMenuContribution } from './file-download-menu-contribution'; | ||
import { FileDownloadCommandContribution } from './file-download-command-contribution'; | ||
|
||
export default new ContainerModule(bind => { | ||
bind(FileDownloadService).toSelf().inSingletonScope(); | ||
bind(CommandContribution).to(FileDownloadCommandContribution).inSingletonScope(); | ||
bind(MenuContribution).to(FileDownloadMenuContribution).inSingletonScope(); | ||
}); |
24 changes: 24 additions & 0 deletions
24
packages/file-download/src/browser/file-download-menu-contribution.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright (C) 2018 TypeFox and others. | ||
* | ||
* Licensed 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 | ||
*/ | ||
|
||
import { injectable } from 'inversify'; | ||
import { MenuContribution, MenuModelRegistry } from '@theia/core/lib/common/menu'; | ||
import { NavigatorContextMenu } from '@theia/navigator/lib/browser/navigator-contribution'; | ||
import { FileDownloadCommands } from './file-download-command-contribution'; | ||
|
||
@injectable() | ||
export class FileDownloadMenuContribution implements MenuContribution { | ||
|
||
registerMenus(registry: MenuModelRegistry) { | ||
registry.registerMenuAction(NavigatorContextMenu.MOVE, { | ||
commandId: FileDownloadCommands.DOWNLOAD.id, | ||
label: 'Download', | ||
order: 'z' // Should be the last item in the menu group. | ||
}); | ||
} | ||
|
||
} |
Oops, something went wrong.