2

I am Developing an app with a feature that downloads some records and saves those as a text file. It's working if I put a static location for the resulting file. I want to let the user decide where they want to save this file. Is there a SaveFileDialog in Asp.Net Core 2.2 MVC?

My Download action in my controller is below:

 public async Task<IActionResult> DownloadList([Bind("Id,isDownload")] BdoPE bdoPE)
        {
            UserDetails();
            string cncuser = ViewBag.DisplayName;
            var config = new CsvHelper.Configuration.Configuration();
            config.Delimiter = "\t";

            var records = new List<BdoRpt>();

            var record = _context.bdoPEs.Where(
                    c => c.DocType != null &&
                    c.isDownloaded == false &&
                    c.CompanyCode != null && 
                    c.AssignNum != null &&
                    c.ItemText != null &&
                    c.ItemText2 != null && 
                    c.isDownloaded == false &&
                    c.MarketerZ2 == cncuser).ToList();

            if (record.Count > 0)
            {
                foreach (var data in record)
                {
                    records.Add(new BdoRpt()
                    {
                        DocDateInDoc = data.DocDateInDoc,
                        DocType = data.DocType,
                        CompanyCode = data.CompanyCode,
                        PosDateInDoc = data.PosDateInDoc,
                        FiscalPeriod = data.FiscalPeriod,
                        CurrentKey = data.CurrentKey,
                        RefDocNum = data.RefDocNum,
                        DocHeadT = data.DocHeadT,
                        PosKeyInNextLine = data.PosKeyInNextLine,
                        AccMatNextLine = data.AccMatNextLine,
                        AmountDocCur = data.AmountDocCur,
                        ValDate = data.ValDate,
                        AssignNum = data.AssignNum,
                        ItemText = data.ItemText,
                        PosKeyInNextLine2 = data.PosKeyInNextLine2,
                        AccMatNextLine2 = data.AccMatNextLine2,
                        AmountDocCur2 = data.AmountDocCur2,
                        BaseDateDueCal = data.BaseDateDueCal,
                        ItemText2 = data.ItemText2,
                    });
                }

                using (var writer = new StreamWriter("C:\\file.txt")) // this is the static location
                using (var csv = new CsvWriter(writer, config))
                {
                    csv.WriteRecords(records);
                }
                recordDownloaded();
                var bdope = _context.bdoPEs.Where(
                    c => c.DocType != null &&
                    c.isDownloaded == false &&
                    c.CompanyCode != null &&
                    c.AssignNum != null &&
                    c.ItemText != null &&
                    c.ItemText2 != null &&
                    c.isDownloaded == false).ToList();

                foreach (var data in bdope)
                {
                    data.isDownloaded = true;
                }
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Lsmw));
            }
            else
            {
                NoRecordFound();
                return RedirectToAction(nameof(Lsmw));
            }
        }

In my code currently it is simply the text file on my drive C:\

Stas Ivanov
  • 1,173
  • 1
  • 14
  • 24
Jose Baleros Jr
  • 86
  • 1
  • 2
  • 11
  • No. There isn't. Show the code you already have, you're missing the right type of content-disposition header on the controller method that returns the file most likely. – Adrian Oct 23 '19 at 07:57
  • 2
    What do you mean by "a static location" in this case? If the user is downloading it from their browser, then this is just a matter of specifying the write attachment parts in the content headers, to pop up a browser dialog. But in that case, you wouldn't be able to specify a "static location". If you're trying to get the user to browse the *server's* file system, that feels a lot odder as a requirement. – Jon Skeet Oct 23 '19 at 07:58
  • 1
    I will edit my post , I will add my codes in my controller – Jose Baleros Jr Oct 23 '19 at 07:58
  • You can show a download file dialog instead:
    – Farhad Rahmanifard Oct 23 '19 at 08:04
  • 1
    Instead of saving the file in the controller, you must return the file to the user so the user can save it at a certain location. – lordvlad30 Oct 23 '19 at 08:07
  • @FarhadRahmanifard The link shows how to download a file that is located my wwwroot, but my mine is it gather records from database then write it in text file. – Jose Baleros Jr Oct 23 '19 at 08:16
  • @jose: That's just a matter of "where you get the data from". It doesn't in any way affect the "how do you return the data to the client so that they're prompted where to store it". – Jon Skeet Oct 23 '19 at 10:31

2 Answers2

0

You can show a download file dialog instead:
https://stackoverflow.com/a/50334901/5137920
Please be careful not to use any library that is related to desktop development directly to avoid any compatibility issues.

  • Hi, on the link you gave, `return File(System.IO.File.ReadAllBytes("C:\\file.txt"), "application/pdf");` how to put filters that they can only save the file as .txt? – Jose Baleros Jr Oct 23 '19 at 08:41
  • @jose: You're not going to be able to *prevent* a user from saving a file with whatever extension they want. Even if you could do that at the browser level, how would you stop them from renaming it themselves afterwards? And why do you think your application *should* be able to control what file extension I use on my local computer? – Jon Skeet Oct 23 '19 at 10:32
  • Please read "**Other ways mentioned here**" line in shared answer and also you can find useful info about responding to user request in shape of a file [here](https://www.c-sharpcorner.com/uploadfile/srseelam/file-download-with-save-as-dialog-box-from-browser/) – Farhad Rahmanifard Oct 23 '19 at 10:41
  • Anyway, as @Jon Skeet said, you can not force everything to the users. Here, you may need to create a temp file and send it to them. After that, they may change the file name, type, or even content. – Farhad Rahmanifard Oct 23 '19 at 10:49
  • @FarhadRahmanifard Hi, I've follow the steps and it work but the page is not refreshive my return part `return View(File(System.IO.File.ReadAllBytes(file), "application/octet-stream", "file.txt"));` how to combine this codes? `return View(File(System.IO.File.ReadAllBytes(file), "application/octet-stream", "file.txt"));` and `return RedirectToAction(nameof(Lsmw));` – Jose Baleros Jr Oct 24 '19 at 07:29
  • I am not sure if this is a good way or not but you may able to create two task and execute 2th task (redirect one) after completion of the first task. – Farhad Rahmanifard Oct 24 '19 at 08:51
0

There is no way of displaying a save dialog directly from your application. You should return a FileResult or any derived implementation and let the browser decide what to do with your data. There is a function that can help you in this.

See this link.

Christopher Moore
  • 15,626
  • 10
  • 42
  • 52
Fran
  • 181
  • 8