1

I'm struggling with the ability to take a file from the server and allow a user to download it. On my machine, I was just opening it but since it has gone to production this doesn't seem to be a working solution.

public HttpResponseMessage Post([FromBody]string[] info)
{
    HttpResponseMessage resp = new HttpResponseMessage();
    string html = info[0];
    _file += info[2] + @"\media\";

    try
    {                
        using (StreamWriter sw = File.CreateText(_file))
        {
            for (int n = 0; n <= str.Length; n = n + 2)
            {.WriteLine(str[n]);
            }
        }
        do
        {
            string notepadPath = Environment.SystemDirectory + "\\notepad.exe";

            var startInfo = new ProcessStartInfo(notepadPath)
            {
                WindowStyle = ProcessWindowStyle.Maximized,
                Arguments = _file
            };

            Process.Start(startInfo);
            break;
        } while (true);
    }
    catch (Exception ex)
    {
        //handled
    }

    return resp;
}

I have attempted to implement something like this but I was unable to configure it to even build. If that really is the best route to go, can someone explain it in detail and how to go about doing it?

Community
  • 1
  • 1
Corey Whaley
  • 66
  • 3
  • 11

3 Answers3

0

In production, you won't be able to start a NotePad.exe process on the web server and expect anyone to be able to access it.

The only thing the web server can do is emit the file in the HTTP response with content-disposition: attachment; filename=something.txt and hope the client has NotePad.exe mapped to the right content type/extension.

John Wu
  • 50,556
  • 8
  • 44
  • 80
0

This worked for me using MVC 5. Hope it works for you as well! :) Keep in mind that the client machine will need to decide what to do with the file on its own - you really don't have any control to start processes on a client machine like that. Down that path lies complete HTTP anarchy.

In the case that you're creating the text file on the fly, you can get by with just using the System.Text.Encoding.UTF8.GetBytes(yourStringHere) without actually creating a file at all - save yourself some disk IO and all that...

    public void DownloadTest()
    {
        var filePath = @"c:\code\testFile.txt";
        var reader = new StreamReader(filePath);
        var data = reader.ReadToEnd();
        var dataBinary = System.Text.Encoding.UTF8.GetBytes(data);

        Response.ContentType = "text/plain";
        Response.AddHeader("content-disposition", "attachment; filename=data.txt");

        Response.BinaryWrite(dataBinary);
    }
CodeHxr
  • 855
  • 8
  • 17
  • So you are saying I should create a void method and pass it the file path, and utilize this code? Can you explain where 'Reponse' comes from? – Corey Whaley Mar 15 '17 at 15:02
  • I used a void method because when you do Response.BinaryWrite(...) you're not actually returning anything. The response object is built-in with MVC if this method existis in a controller. I think that most flavors of ASP.NET have some kind of Response object you can access. – CodeHxr Mar 15 '17 at 15:07
  • Oh, as for the file path, you can certainly do that, but if you're making the text file on the fly as you alluded to in the question comments, you can eliminate the first 3 variables (filePath, reader, data) and just do `var dataBinary = System.Text.Encoding.UTF8.GetBytes(whateverStringYouGenerated);` – CodeHxr Mar 15 '17 at 15:09
0

Based on your comments, the following should do:

public HttpResponseMessage Post([FromBody]string[] info)
{
    // create your file on the fly.
    var txtBuilder = new StringBuilder();
    for(int n = 0; n <= str.Length; n = n + 2)
    {
        txtBuilder.AppendLine(str[n]);
    }

    // make it as a stream
    var txtContent = txtBuilder.ToString();
    var txtStream = new MemoryStream(Encoding.UTF8.GetBytes(txtContent));

    // create the response and returns it
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new StreamContent(txtStream);
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
    {
        FileName = info[0] // Not sure about that part. You can change to "text.txt" to try
    };

    return result;
}

I am not sure how you get the file name and what kind of extension it is, but you can modify the FileName as well as the Mime Type in order to accomplish what you need.

StfBln
  • 1,137
  • 6
  • 11