Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-1905: Implemented the file download functionality. #2114

Merged
merged 1 commit into from
Jun 22, 2018
Merged

Conversation

kittaakos
Copy link
Contributor

@kittaakos kittaakos commented Jun 14, 2018

Closes #1905.

Signed-off-by: Akos Kitta kittaakos@gmail.com

@kittaakos kittaakos changed the title [WIP] GH-1905: Implemented the single file download functionality. GH-1905: Implemented the file download functionality. Jun 15, 2018
@kittaakos
Copy link
Contributor Author

It is ready for the review.

@kittaakos kittaakos force-pushed the GH-1905 branch 2 times, most recently from 4e1c3f1 to d567576 Compare June 15, 2018 13:44
Copy link
Contributor

@svenefftinge svenefftinge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could move most of this to filesystem. The context menu registration could be moved to navigator.

/**
* `true` if the argument is an empty object. Otherwise, `false`.
*/
export function isEmpty(arg: Object): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need to check the constructor : arg.constructor === Object as in theory there can be other objects without own properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@injectable()
export class FileDownloadEndpoint implements BackendApplicationContribution {

protected static PATH = '/file-download';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be just files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

if (uris.length === 1) {
return true;
}
// Can download multiple files iff they are from the same container folder.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why restrict it like that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am OK removing the restriction if you could help me define a clear way how the files should be zipped up in a folder when selecting multiple files "randomly" from a workspace.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could preserve the structure and use the common parent of all files as the container.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same idea, then I thought; we have to overcomplicate the backend logic for a feature which we won't use that frequently anyway, but let's do.

@kittaakos
Copy link
Contributor Author

We could move most of this to filesystem. The context menu registration could be moved to navigator.

I did not want to. I think it is nice to have it in its extension. It is always easier to customize and put together an application from tiny extensions than registering my own sub-classes, override methods here and there and then rebind then for instance, when I want to disable/change the default functionality.

But I could move it to the WS and FS.

@svenefftinge
Copy link
Contributor

I would prefer it. Each extension adds a lot of infrastructural overhead (and degrades build performance) so it needs to be balanced when we create a new extension. I think in this case it tends towards having it in file-system as it is an endpoint exposing it.

@kittaakos
Copy link
Contributor Author

Each extension adds a lot of infrastructural overhead (and degrades build performance)

It is unfortunate, we have to define extensions and adapt the code to this, but I see your point.

@svenefftinge
Copy link
Contributor

Also, could we use tar instead of zip?
Zipping takes too long and blocks the node process. Also Users don't get any kind of progress feedback. Using tar instead makes that part fast and moves the work to the download, which has already a nice progress :).

@kittaakos
Copy link
Contributor Author

Also, could we use tar instead of zip?

What can I do with a tar as a Windows user? I am just asking... I am not aware of any built-in tools that unpack the tar on Windows. Is it a good idea to force users to use 7Zip?

@svenefftinge
Copy link
Contributor

@kittaakos did you see the build failures?

@kittaakos
Copy link
Contributor Author

Thanks for the note: no. I am still in the middle of the changes; the commits are not yet squashed... I will ping you here when it is ready for the review.

@kittaakos
Copy link
Contributor Author

@svenefftinge, I have made a few changes regarding the multi-file download feature; I would consider this PR ready for review.

@svenefftinge
Copy link
Contributor

Downloading a directory (e.g. packages in theia repo) is still taking far too long to go without any kind of user feedback. We should at least add an item to the statusbar : preparing download ... with some spinning icon or so until the response comes in.

@kittaakos
Copy link
Contributor Author

We should at least add an item to the statusbar : preparing download ... with some spinning icon or so until the response comes in.

OK.

@kittaakos
Copy link
Contributor Author

I did some measurements, and the bottleneck is the archiving part: this takes 29430 ms when downloading the node_modules folder (573.2 MB) from Theia. I will try to pipe the archiving stream into the response. Hopefully, it makes the user experience smoother, if no, I update the status bar to give some user feedback.

@kittaakos
Copy link
Contributor Author

I have managed to pipe the tar stream into the response but the download progress indicator did not show up in the browser even with downloadjs. I go with the status bar approach.

@kittaakos
Copy link
Contributor Author

We should at least add an item to the statusbar : preparing download ... with some spinning icon or so until the response comes in.

This is done.

@kittaakos
Copy link
Contributor Author

I tried to fine-tune the status bar's Preparing download... visibility. It is still not perfect; see the attached screen-casts below. I have already moved the status bar updating logic to the very last possible position where I still do "have control" over the download.

This could be the root of the defect (source: whatwg/html#954 (comment)):

[...]The problem is that browsers tend to start the download asynchronously after the link has been clicked. This is especially browsers which show the user a "do you want to open or download this file?" dialog, where the download might start long after the link was clicked.[...]

Downloading packages:
gh-1905-packages-download

Downloading node_modules (cut):
gh-1905-node_modules-download-cut

Downloading theia (cut):
gh-1905-theia-download-cut

Closes #1905.

Signed-off-by: Akos Kitta <kittaakos@gmail.com>
Copy link
Contributor

@svenefftinge svenefftinge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@kittaakos kittaakos merged commit 4dfc327 into master Jun 22, 2018
@kittaakos kittaakos deleted the GH-1905 branch June 22, 2018 08:22
@davide-sergi
Copy link

Is there a flow diagram somewhere in order to understand how download a file/folder programmatically?

@kittaakos
Copy link
Contributor Author

flow diagram

No, there isn't. At least, I am not aware of it.

how download a file/folder programmatically?

Check this thread. It might be outdated, though. If it does not work now, please open a follow-up issue, or start a discussion, to attract more attention for your problem. This is a closed PR.

I hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow to download files from the workspace
3 participants