0

I'm doing the below to upload a .pptx file and save it on the disk of the server.

When I try to open the file, it says that it's corrupt, and cannot be opened.

Is this because of my encoding type or something different?

Is it possible to send any arbitrary file as binary in an POST and have it reach the server in one piece?

    public static void ListenerCallback(IAsyncResult result)
    {
        HttpListener listener = (HttpListener)result.AsyncState;
        HttpListenerContext context = listener.EndGetContext(result);
        HttpListenerRequest request = context.Request;
        HttpListenerResponse response = context.Response;
        StreamReader reader = new StreamReader(request.InputStream);
        var res = reader.ReadToEnd();
        reader.Close();
        toLog.Add(res);
        NameValueCollection coll = HttpUtility.ParseQueryString(res);
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(res);
        File.WriteAllBytes("output.pptx", bytes);
        response.StatusCode = 200;
        response.ContentType = "text/html";
        using (StreamWriter writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF8))
            writer.WriteLine("File Uploaded");
        response.Close();
    }

This is the Postman preview of what I'm sending:

POST  HTTP/1.1
Host: localhost:80
Content-Type: application/vnd.openxmlformats-officedocument.presentationml.presentation
Cache-Control: no-cache
Postman-Token: 9a04aa33-cd44-d238-6873-b330524f4ae5

undefined

If I open up the source (non-corrupt) file in np++, I see that the editor chooses to encode it in ANSI.

I'm currently encoding it in UTF8, and I don't appear to have the option to encode in ANSI.

Also, when comparing the file size, I lose a kilobyte of data.

EDIT: My current code is now this

This writes an empty file to the disk.

    public static void ListenerCallback(IAsyncResult result)
    {
        HttpListener listener = (HttpListener)result.AsyncState;
        HttpListenerContext context = listener.EndGetContext(result);
        HttpListenerRequest request = context.Request;
        HttpListenerResponse response = context.Response;

        StreamReader reader = new StreamReader(request.InputStream);
        var res = reader.ReadToEnd();
        reader.Close();
        Console.WriteLine(res);
        NameValueCollection coll = HttpUtility.ParseQueryString(res);

        using (var outp = File.OpenWrite("output.pptx"))
        {
            request.InputStream.CopyTo(outp);
        }

        response.StatusCode = 200;
        response.ContentType = "text/html";
        using (StreamWriter writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF7))
            writer.WriteLine("File Uploaded");
        response.Close();
    }
  • What do you think you're doing? You're writing the bytes to a file called `output.pptx` on your server's disk. Are you trying to send that file to the browser? – John Saunders Aug 19 '14 at 23:45
  • @JohnSaunders I would like to write the bytes to a file called `output.pptx` on my server's disk –  Aug 19 '14 at 23:51
  • Then why are you using encoding? It's binary - just write it. How is the file being sent to you? ``? – John Saunders Aug 20 '14 at 00:06
  • Also, what's the context here? What kind of application is this? – John Saunders Aug 20 '14 at 00:08
  • @JohnSaunders Because the binary is represented as a String. I'm trying to upload a powerpoint to my server using a POST and then store it on the disk of the server in a way that it isn't corrupted and unusable. Is there a way I can not have the binary be represented as a String? –  Aug 20 '14 at 00:13
  • What makes you think it's "represented as a string"? It's just binary. Try writing `res` and see what happens. – John Saunders Aug 20 '14 at 00:21
  • @JohnSaunders How do I write `res`? –  Aug 20 '14 at 00:24
  • @JohnSaunders According to http://stackoverflow.com/questions/411592/how-do-i-save-a-stream-to-a-file , If you use StreamReader on a binary stream, you get corrupt data. I use `StreamReader` to get `res`, so even if I do write `res`, it'll be corrupt. I'm currently trying to figure out how to write `request.InputStream` –  Aug 20 '14 at 00:34

2 Answers2

0

I think it's because you're sending it as MIME type "text/html", rather than the correct type "application/vnd.openxmlformats-officedocument.presentationml.presentation".

timbck2
  • 1,036
  • 3
  • 15
  • 36
  • I tried that and it didn't work. I'll post the request that I'm sending C# –  Aug 19 '14 at 23:38
0

I don't have time to test this right now, but try this:

public static void ListenerCallback(IAsyncResult result)
{
    HttpListener listener = (HttpListener)result.AsyncState;
    HttpListenerContext context = listener.EndGetContext(result);
    HttpListenerRequest request = context.Request;
    HttpListenerResponse response = context.Response;

    using (var out = File.OpenWrite("output.pptx"))
    {
        request.InputStream.CopyTo(out);
    }

    response.StatusCode = 200;
    response.ContentType = "text/html";
    using (StreamWriter writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF8))
        writer.WriteLine("File Uploaded");
    response.Close();
}
John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • This results in a 0 byte file with the name `output.pptx` being written, after you change the variable "out" to something that isn't a reserved word. –  Aug 21 '14 at 16:09
  • Actually, no, that works. I just didn't copy your code verbatim. Your code leaves out the whole "get query string in a NameValueCollection" section, which necessitates me having to "rewind" the stream to the beginning before doing this –  Aug 21 '14 at 16:29
  • I didn't see your code doing anything with the query string, so I got rid of that. – John Saunders Aug 21 '14 at 17:29