WebView2Feedback icon indicating copy to clipboard operation
WebView2Feedback copied to clipboard

SaveAs functionality

Open jgrahovac opened this issue 4 years ago • 36 comments

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

jgrahovac avatar Mar 18 '21 16:03 jgrahovac

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

aks1008 avatar Mar 20 '21 06:03 aks1008

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

champnic avatar Mar 23 '21 00:03 champnic

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.

rgup63 avatar Apr 19 '21 05:04 rgup63

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

champnic avatar Apr 19 '21 21:04 champnic

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

rgup63 avatar Apr 21 '21 04:04 rgup63

Done :)

champnic avatar Apr 21 '21 18:04 champnic

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!

szanto90balazs avatar Oct 21 '21 15:10 szanto90balazs

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

champnic avatar Oct 22 '21 05:10 champnic

Just dropping a line - I assumed this capability would be available and wasted 6 hours today.

Also, WHY ISN'T THIS OPEN SOURCE???

This is exactly the sort of thing that should be - it boggles the mind in fact. You wrote a closed-source, verifiably half-a**ed web browser control for your open-source-based browser to be used on your open source dev platforms... and you made it closed.

No DOM, no ability to save pages... this remains a HUGE regression from the IE controls. I'd be better off reparenting the window or some whacky alternative.

JMPZ11 avatar Feb 09 '22 01:02 JMPZ11

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.

nishitha-burman avatar Jun 08 '22 23:06 nishitha-burman

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.

szanto90balazs avatar Jun 09 '22 19:06 szanto90balazs

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

nishitha-burman avatar Jun 14 '22 17:06 nishitha-burman

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.

ghost avatar Jun 14 '22 17:06 ghost

@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 avatar Jun 16 '22 18:06 szanto90balazs

@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.

szanto90balazs avatar Jul 26 '22 09:07 szanto90balazs

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

nishitha-burman avatar Jul 26 '22 22:07 nishitha-burman

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 avatar Aug 17 '22 18:08 champnic

@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.

champnic avatar Aug 18 '22 19:08 champnic

@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 avatar Aug 19 '22 12:08 Mips128

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?

Mips128 avatar Nov 11 '22 09:11 Mips128

Hi @Mips128,

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

nishitha-burman avatar Nov 11 '22 21:11 nishitha-burman

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!

nishitha-burman avatar Jan 12 '23 22:01 nishitha-burman

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

mikkelmogensen avatar Jan 12 '23 22:01 mikkelmogensen

@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.

donid avatar Jan 19 '23 08:01 donid

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!

nishitha-burman avatar Jan 26 '23 23:01 nishitha-burman

@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.

donid avatar Jan 27 '23 05:01 donid

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

nishitha-burman avatar Jan 27 '23 18:01 nishitha-burman

@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).

donid avatar Jan 27 '23 19:01 donid

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

AndreaMontanari89 avatar Jan 27 '23 19:01 AndreaMontanari89

@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"?

nishitha-burman avatar Feb 08 '23 17:02 nishitha-burman