1

Question: I want to know how a file is read if sent to an end point.

After reading multiple articles and doing some research I am able to send a file to Amazon S3 bucket. Below is the working code but I don't understand how a file is sent to my API via Postman and how processing happens, how this file is being read in the code. Can someone please help me decode this code.

I have added line numbers to the code I want to understand.

Line Number

1 [httppost]
2 public async Task<bool> Upload()
  {
    try
    {
3       var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
4       foreach (var content in filesReadToProvider.Contents)
        {
5           var stream = await content.ReadAsStreamAsync();
6           using (StreamReader sr = new StreamReader(stream))
            {
                string line = "";
7               while ((line = sr.ReadLine()) != null)
                {
8                   using (MemoryStream outputStream = new MemoryStream())
9                   using (StreamWriter sw = new StreamWriter(outputStream))
                    {
                        sw.WriteLine(line);
10                      sw.Flush();
                        PutRecordRequest putRecord = new PutRecordRequest();
                        putRecord.DeliveryStreamName = myStreamName;
                        Record record = new Record();
11                      outputStream.Position = 0;
                        record.Data = outputStream;
                        putRecord.Record = record;
                        try
                        {
                            await kinesisClient.PutRecordAsync(putRecord);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Failed to send record to Kinesis. Exception: {0}", ex.Message);
                        }
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
    }

    return true;
  }

P.S: I am sending a file via Postman for testing the working of this end point.

My undertanding of above code.

Line Number 1: It's a HTTPPOST request, so that means the content I am sending will be in the body of the request and not in the headers or the URL. Since I am sending a file, the file content will be sent in the body of the request.

Line Number 2: asyn so it will be run on a separate thread so my UI (if any) will be responsive.

Line Number 3: I am guessing Request is basically a handle to read the body content for any API Requests, so I am reading the content using Request.Content,
Question: What is the meaning of ReadAsMultipartAsync: it says: Reads all body parts within a MIME multipart message and produces a set of System.Net.Http.HttpContent instances as a result.? What this means? Does this mean the if my file has 10 lines, it is reading all 10 lines and kind of storing it in the memory (in layman terms)?

Line Number 4: I am guessing filesReadToProvider.Contents is again a handle for all those 10 lines that I have in file. Does that mean if I have 10 lines in my file this will loop will run for 10 times (I think I am wrong here).

Line Number 5: ReadAsStreamAsync it says: Serialize the HTTP content and return a stream that represents the content as an asynchronous operation.. Does this mean that it is reading 1 line at a time and serializing it? But why it is serializing the lines?

LineNumber 6: Since I have streams to deal with I am creating a streamreader instance and passing the stream to it. (in layman terms: I am passing one line of file that I am reading)?

Beyond this I am lost. I am totally confused after this. What is a stream? Is it one line in my file?

Question: Please someone help me in understading what is happening in above code. I don't think I can directly link a line of file with a stream. Please guide me.

Unbreakable
  • 7,776
  • 24
  • 90
  • 171

2 Answers2

2

Line 1: Setup the method to respond to HttpPost

Line 2: async means go off and perform the task (which can be on a separate thread and will be in this case), and re-call this method when that task has completed or failed.

Line 3: Multipart HTTP is a standard often used for sending files What is http multipart request?

Line 4: This is the different contents of the Multipart request the user has sent.

Line 5: Get the contents of this part as a stream. A stream performs byte reading only and isn't very user friendly. Hence the StreamReader in Line 6.

Line 6: Creates a StreamReader, which is a helper class to allow line by line processing of a Stream.

Line 7: do a loop, getting line's as a string, until we hit a null.

Line 8: Construct a memory stream. A memory stream is a stream where the read/write operations are performed in memory rather than from a network or disk.

Line 9: Use a StreamWriter around the memory stream. StreamWriter is a helper class that will allow easier line based operations.

Line 10: Use the StreamWriter to write the current lines from the loop started in line 7. We Flush it so that it has the full line inside of it. If we don't do this potentially it won't have all the content. Streams by default will buffer, meaning they will delay their read/writes until enough data has been added to them as a performance optimisation. This forces that read/write operation.

Line 11: If we don't set the location of the MemoryStream back to 0, it'll attempt to read AFTER the line has been inserted. This sets it back to the beginning of the line. MemoryStream are basically a byte buffer with what you put inside of them, along with the current Read/Write location information.

Glenn Watson
  • 2,758
  • 1
  • 20
  • 30
  • 1
    Great answer. Also wanted to point out that on line 6, line 8 and line 9 the "using" statements ensure that the declared resources (in this case `StreamReader sr`, `MemoryStream outputStream` and `StreamWriter sw`, will be disposed when leaving the scope `{ }`. [Check here](https://stackoverflow.com/questions/75401/what-are-the-uses-of-using-in-c-sharp) – n0idea Feb 14 '19 at 09:19
0

A stream is a flow of data, you can have many different types. A StreamReader will read in the file and it needs a stream to read it into. You are not passing a line from the file, you are basically opening a file and reading it's contents into the stream asynchronously. People sometimes use streams like this when the actual data is too large to read into memory all at once before being written out.

This code uses a memory stream to buffer the info that it reads from file and the KinesisClient to write it out. I'm not really familiar with the KinesisClient but given that you say the code works I'd say it is gracefully handling parsing the stream it is being passed to write out the info.

justjoshin
  • 114
  • 6