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

SaveAs functionality #1090

Open
jgrahovac opened this issue Mar 18, 2021 · 36 comments
Open

SaveAs functionality #1090

jgrahovac opened this issue Mar 18, 2021 · 36 comments
Assignees
Labels
feature request feature request tracked We are tracking this work internally.

Comments

@jgrahovac
Copy link

jgrahovac commented Mar 18, 2021

I'm using WebView2 in C++. How can I implement SaveAs option from right click menu? It is supposed to launch SaveAs dialog to save html file.

AB#32723386

@aks1008
Copy link

aks1008 commented Mar 20, 2021

Hi @jgrahovac,

Not sure how to implement it is the C++. But if you have implemented already it and it is not working, it might be due to you are running application in Administrator mode. I have faced similar problem. I had WPF application where I was using SaveAs and Print functionality of WebView2, but it was not opening SaveAs dialog box. It was due to Admin mode.

Hope this might help you. Happy Coding :)

Thanks,
AkshayL

@champnic
Copy link
Member

If this is the admin/elevated issue, we are tracking that in #802. Otherwise I would expect this to just work.

@champnic champnic self-assigned this Mar 23, 2021
@rgup63
Copy link

rgup63 commented Apr 19, 2021

Does webview2 support ShowSaveAsDialog() to open save dialog box? I can see same is supported in IE based web browser like this WebBrowser.ShowSaveAsDialog(); . I am looking for something similar to this in webview2.

@champnic
Copy link
Member

@rgup63 No we don't support that as a WebView2 API today. Do you want me to open that as a feature request?

@rgup63
Copy link

rgup63 commented Apr 21, 2021

@champnic Yes please, I think it would be good if webview2 supports this feature.

@champnic champnic added feature request feature request tracked We are tracking this work internally. and removed question labels Apr 21, 2021
@champnic
Copy link
Member

Done :)

@szanto90balazs
Copy link

Hi @champnic 👋

Any update on this one? It would be a very useful feature to programmatically trigger the "Save As" flow, since the Ctrl+S hotkey is disabled (which is documented here: https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/browser-features). Currently the only available option is to use the context menu. This way it's not possible to add the "Save As" to the main menu and assign a hotkey to it.

The only way "Save" can be triggered, if customization is made to the context menu. Still, this is only restricted to the context menu and it's also an experimental feature as of today.

Last, I think it would worth removing the Ctrl+S input gesture text from the "Save As" context menu item, as it is disabled on purpose.

image

Thanks in advance!

@champnic
Copy link
Member

Hi @szanto90balazs! No update on this one yet, sorry!

@JasonJShuler

This comment was marked as off-topic.

@nishitha-burman
Copy link
Collaborator

nishitha-burman commented Jun 8, 2022

Hello,

You can use JavaScript APIs to implement SaveAs. Here is an example:

var request = new XMLHttpRequest();
request.open("GET", "https://www.bing.com/");
request.responseType = "text";
request.send();
request.addEventListener("loadend", loadEnd);
async function loadEnd(e) {
    const content = request.responseText;
    const opts = {
        types: [{
            description: 'html file',
            accept: { 'text/html': ['.html'] },
        }],
    };
    const handle = await window.showSaveFilePicker(opts);
    const writable = await handle.createWritable();
    writable.write(content);
    writable.close();
}

Let us know if this addresses your scenario.

@szanto90balazs
Copy link

Hello @nishitha-burman,

We aim to download all the assets related to the page. If I understand it correctly, the proposed solution only downloads the HTML page, but not the other assets (CSS, JS, image files, ...) as opposed to the browser's SaveAs functionality.

@nishitha-burman
Copy link
Collaborator

Hi @szanto90balazs,

Thank you for your reply. We are currently investigating. Some follow-up questions:

  1. Can you please describe your scenario where you would like to use SaveAs programmatically?
  2. Would you like this functionality triggered by any hotkey?
  3. What file format(s) would you like to save the file as?
  4. Do you want to save the assets into different folders or everything in one file?

Thank you,
Nishitha

@yildirimcagri-msft
Copy link
Member

Hi @szanto90balazs, unfortunately, we don't have a direct API to do this right now. However if you can send input to the WebView2 window, there is a workaround. You can send a right click input and handle the ContextMenuRequested event by setting the SelectedCommandId property to the "Save As" item, which will run that command.

@szanto90balazs
Copy link

@nishitha-burman I'll try to answer your follow up questions:

Can you please describe your scenario where you would like to use SaveAs programmatically?

From the context menu, from any WPF menu which might be shared globally across webview instances or using a global hotkey

Would you like this functionality triggered by any hotkey?

Yes.

What file format(s) would you like to save the file as?

The same formats that's offered by the "Save as" dialog triggered from the context menu.

Do you want to save the assets into different folders or everything in one file?

It would be good enough to stick to the same formats provided just like Save As does.

image

@yildirimcagri Good idea, I'll look into it.

@szanto90balazs
Copy link

szanto90balazs commented Jul 26, 2022

@yildirimcagri The workaround you suggested worked great. I was also able to override the global Ctlr+S shortcut, so I can trigger SaveAs using key bindings.

This SO post helped significantly with the implementation. Some changes will be needed to it, though: https://stackoverflow.com/questions/6554494/how-can-i-send-a-right-click-event-to-an-automationelement-using-wpfs-ui-automa

See code example:

public static void RightClick(this AutomationElement element)
{
    Point p = element.GetClickablePoint();

    NativeStructs.Input input = new NativeStructs.Input
    {
        type = NativeEnums.SendInputEventType.Mouse,
        mouseInput = new NativeStructs.MouseInput
        {
            dx = 0,
            dy = 0,
            mouseData = 0,
            dwFlags = NativeEnums.MouseEventFlags.Absolute | NativeEnums.MouseEventFlags.RightDown | NativeEnums.MouseEventFlags.Move,
            time = 0,
            dwExtraInfo = IntPtr.Zero,
        },
    };

        var primaryScreen = Screen.PrimaryScreen;
        input.mouseInput.dx = Convert.ToInt32((p.X - primaryScreen.Bounds.Left) * 65536 / primaryScreen.Bounds.Width);
        input.mouseInput.dy = Convert.ToInt32((p.Y - primaryScreen.Bounds.Top) * 65536 / primaryScreen.Bounds.Height);
    NativeMethods.SendInput(1, ref input, Marshal.SizeOf(input));
    input.mouseInput.dwFlags = NativeEnums.MouseEventFlags.Absolute | NativeEnums.MouseEventFlags.RightUp | NativeEnums.MouseEventFlags.Move;
    NativeMethods.SendInput(1, ref input, Marshal.SizeOf(input));
}

internal static class NativeMethods
{
    [DllImport("user32.dll", SetLastError = true)]
    internal static extern uint SendInput(uint nInputs, ref NativeStructs.Input pInputs, int cbSize);
}

internal static class NativeStructs
{
    [StructLayout(LayoutKind.Sequential)]
    internal struct Input
    {
        public NativeEnums.SendInputEventType type;
        public MouseInput mouseInput;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct MouseInput
    {
        public int dx;
        public int dy;
        public uint mouseData;
        public NativeEnums.MouseEventFlags dwFlags;
        public uint time;
        public IntPtr dwExtraInfo;
    }
}

internal static class NativeEnums
{
    internal enum SendInputEventType : int
    {
        Mouse = 0,
        Keyboard = 1,
        Hardware = 2,
    }

    [Flags]
    internal enum MouseEventFlags : uint
    {
        Move = 0x0001,
        LeftDown = 0x0002,
        LeftUp = 0x0004,
        RightDown = 0x0008,
        RightUp = 0x0010,
        MiddleDown = 0x0020,
        MiddleUp = 0x0040,
        XDown = 0x0080,
        XUp = 0x0100,
        Wheel = 0x0800,
        Absolute = 0x8000,
    }
}

Works with multiple displays as well, but the example code needs to be changed to get the screen the WebView2 is displayed on.

@nishitha-burman
Copy link
Collaborator

Sounds good, thanks for the update @szanto90balazs. Closing this issue since the workaround works.

@champnic
Copy link
Member

We've removed the "Ctrl+S" hotkey text from the context menu, and it should be in runtime versions 105.0.1340.0+.

We're also going to reopen this issue to track future improvements to invoking SaveAs. While there is a workaround that exists, it's relatively cumbersome and non-intuitive.

@champnic champnic reopened this Aug 17, 2022
@champnic
Copy link
Member

@Mips128 from issue #2654 was also asking for the ability to set a path and type when saving to avoid launching the dialog and initiate the save silently.

@Mips128
Copy link

Mips128 commented Aug 19, 2022

@champnic thanks for integrating this feature request into this ticket. I just want to point out that the discussed work around does not work in our case, due to the save dialog that appears.

@Mips128
Copy link

Mips128 commented Nov 11, 2022

I just want to kindly ask the following two questions:
Do you have any news regarding this feature request? Do you know if and when it will be implemented?

@nishitha-burman
Copy link
Collaborator

Hi @Mips128,

This feature request is in our backlog and something we will be looking into next year.

@nishitha-burman
Copy link
Collaborator

nishitha-burman commented Jan 12, 2023

Hello,

We are looking into this feature and I have a couple of questions:

  1. What kind of file types are you looking for support with the SaveAs functionality (e.g. HTML pages, PDF, images, video, etc.)?
  2. Are you looking to build your own SaveAs dialog, trigger a built in one, or require no dialog (silent SaveAs)?
  3. If you want to use a built in SaveAs dialog, what kind of customizations do you require? Are you looking for the ability to also close the dialog?
  4. Do you require to set a default file path to save the file in?

@Mips128, @jgrahovac, @aks1008, @rgup63, @szanto90balazs

Thank you!

@mikkelmogensen
Copy link

I am looking to build my own SaveAs dialog for HTML pages, PDF, images, video, etc

@donid
Copy link

donid commented Jan 19, 2023

@nishitha-burman
Hi, I have been hoping that WebView2 would implement SaveAs for quite a while.
For me, the MHTHML format would be most important, so that I can save (archive) a whole page.
Similar to PrintToPdfAsync and PrintToPdfStreamAsync it is always useful to be able to specify a filename or to receive a stream instance. This would provide great flexibility and the SaveAs API would be consistent to PrintToPdf.

@nishitha-burman
Copy link
Collaborator

Thank you for the feedback @mikkelmogensen and @donid. We are currently working on a SaveAs API and I would like to better understand your requirements. @donid are you looking to build your own SaveAs dialog or trigger the built-in SaveAs dialog? Are you also looking for an API to close the dialog?

Thanks!

@donid
Copy link

donid commented Jan 27, 2023

@nishitha-burman
I am very happy to hear that this feature is in progress.
My use-case would be to save pages as MHTML to a common folder that has been configured in advance - so, I would not need to use the built-in SaveAs dialog.

@nishitha-burman
Copy link
Collaborator

@donid Thanks for the details. To clarify, you don't require any SaveAs dialogs (custom or built in)?

@donid
Copy link

donid commented Jan 27, 2023

@nishitha-burman
I am planing to use the SaveAs (MHTML) feature in a WinForms application. Maybe I will (optionally) allow the user to specify a filename by invoking the SaveFileDialog component that is provided by WinForms. Even if I would allow the user to choose the file format, that could easily be done with that component. So, I don't see any advantage in having api-access to WebView2's SaveAs dialog. Another scenario where I might use the new SaveAs feature is automated saving of web-pages, controlled by a command line interface (no dialogs at all).

@AndreaMontanari89
Copy link

Same scenario for me, can't wait for this feature! ✌️

@nishitha-burman
Copy link
Collaborator

@mikkelmogensen can you provide more details on your scenario for PDF, images, video? Are you looking support for a scenario where you save the whole page that contains images, pdf, video or the scenario where end user hovers over an image or pdf and do "Save-image-as"?

@mikkelmogensen
Copy link

@nishitha-burman
Thanks for providing this feature
I am looking for both.

I have built my own dialog window for DownloadStarting and now I am looking to build my own SaveAs dialog for complete webpage and PDF and link and image and video.

Maybe some along the lines of SaveAsStarting

I would also like to build my own open/upload dialog, which I don't believe is possible yet, but maybe I will have to open a separate issue?

@5JjLF5jFEhfRU
Copy link

5JjLF5jFEhfRU commented Feb 22, 2023

Edited & rewrote the entire reply:

WebView2 version 1.0.1587.40 has a context menu for a Save As, which matches Edge's & has a MHTML format, so that's great so far.

Question becomes how do we, or can we, access the method programmatically for the Save As so it's a silent Save As? The underlying code is there already.

@first-zhangwei
Copy link

@nishitha-burman @champnic
I have a similar scenario: I have added a custom context menu item and upon clicking it, I can get a download link through the ContextMenuTarget. The problem is how can I start a download task to download the file pointed by this link? Is it possible to support both silent download and non-silent download? Oh, one more question, does Webview2 use multi-threaded downloading by default?

@mikkelmogensen
Copy link

A TotalBytesToReceive property would be appreciated for SaveAsUIShowing event

@Master-Ukulele
Copy link

@mikkelmogensen Do you expect this TotalBytesToReceive property to know the size of contents will be saved?

The answer is no. Because it's out of the scope of SaveAsUIShowing event. The value of total bytes can't be calculated until the saving/downloading starts. This behavior is the same as browser's context menu SaveAs function, so we can't add this property.

@nishitha-burman
Copy link
Collaborator

Hello, the SaveAs API is now available as experimental. Please give it a try and let us know if you have any feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request feature request tracked We are tracking this work internally.
Projects
None yet
Development

No branches or pull requests