2

My project is a Sharepoint Web-App, and it will generate a text file for the user and offer it for the user to download.

The web-app generates a string value and should use FileStream to create a text file out of it. The user clicks a button and they should get a save-as dialogue.

Now, it is simple enough to use FileStream to write to the user's local drive, but how do you prompt them for the location and THEN save it there?

There are lots of questions about how to write to the local disk, and there are questions about how to open the save-dialogue in the browser. But I have not found any that answer the question of using the two methods together.

To write the file, we can use this:

        using (var fs = new FileStream(@"C:\test.txt", FileMode.Create, FileAccess.ReadWrite)) {
            TextWriter tw = new StreamWriter(fs);
            tw.Write("Hello World");
            tw.Flush();
        }

and to open the save-as dialog, we can do this, which will tell the browser a file is ready for downloading which will open the browser's own save dialogue:

            if (resp.IsClientConnected) {
                resp.Clear();
                resp.ClearHeaders();
                //Indicate the type of data being sent
                resp.ContentType = "text/plain";    //".htm", "html" = "text/html"
                resp.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(gentextfilename) + "\"");
                resp.AppendHeader("Content-Length", reader.BaseStream.Length.ToString());
                resp.TransmitFile(file_name); //does not buffer into memory, therefore scales better for large files and heavy usage
                resp.End();
            }

Now, is there a way to combine these? I don't want to save the file to the server and then download it. I want to save it directly to a save location specified by the user. And to make all of this worse, it's a Sharepoint web-app, so it will run inside of Sharepoint, so I don't think you can use the folderBrowserDialog1 or SaveFileDialog method like you can in a desktop application.

Summary of What Answer is Being Sought:

How can I create a file (without creating one on the server) to save to download location of the user's choice?

bgmCoder
  • 6,205
  • 8
  • 58
  • 105
  • Try changing resp.TransmitFile(file_name); to resp.Write(file_name); if I remember correctly, that streams the file to the browser prompting a save as dialog. – RandomUs1r Jun 06 '17 at 22:02
  • Sure, but that still requires an actual file to write. I don't have any file; I only have the stream. – bgmCoder Jun 06 '17 at 22:08
  • Gotcha, can you save it to memory then? https://stackoverflow.com/questions/8624071/save-and-load-memorystream-to-from-a-file . Or... https://stackoverflow.com/questions/16193960/stream-pdf-to-browser – RandomUs1r Jun 06 '17 at 22:22
  • I would love you if you could provide an answer with an example! I'm trying to figure out whether I can do that, but an example that writes the string to the `response` would work wonders for me. – bgmCoder Jun 06 '17 at 22:28
  • I found this: https://stackoverflow.com/questions/13779139/writing-memorystream-to-response-object but I don't know yet if it will work here. – bgmCoder Jun 06 '17 at 22:37

1 Answers1

0

No, there is no way to do that directly as you are used to in Windows desktop development. This is the nature of the protocol used.

You can't use the desktop file dialogs from within your ASP.NET application to ask the user where to save things. You have to rely on the browser to do so.

The best option you have is what you already show: content disposition. Give the browser as much information as you can and let the user decide what to do with it.

If you can use ASP.NET MVC, you can take advantage of the streamed responses, like FileStreamResult or using standard ASP.NET, using CopyTo.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • Yes, I understand I cannot launch the desktop environment's save dialog. My problem is that I can't figure out how to stream to the download location of the user's choice. That's what I want to solve. – bgmCoder Jun 06 '17 at 21:56
  • You can't. The browser determines when and how a file is saved. Not you. You can deliver the response in a streamed way, but it is to ASP.NET and the browser how that is handled. @bgmCoder – Patrick Hofman Jun 06 '17 at 22:01
  • So I either have to save the file to the server and then let the browser download it, or I have to save it to a predetermined location? Is there no middle way? – bgmCoder Jun 06 '17 at 22:07
  • You can't save it to a predetermined way. The browser decides where to save it (and if it asks the user on beforehand or afterwards). You deliver the results (streamed or not) and the browser downloads and saves. – Patrick Hofman Jun 06 '17 at 22:15
  • Then would you say there is no way to do this without having a temp file on the server? – bgmCoder Jun 06 '17 at 22:19
  • You can deliver the response in a streamed matter. You can't force how it is saved on the client though. – Patrick Hofman Jun 06 '17 at 22:22