brk
brk

Reputation: 1456

Stream content as Azure function output

I am working with some files and converting from one format to another. My function is a step in a logic app and the output of my function results in a file being created, using the pre-defined step "Create file (FTP)" where the file content is the body of my function.

I am trying to change the way my function works at the moment to have a memory friendly version. I was trying to achieve some form of 'streaming' so that I essentially only have one object in memory at a given time when deserializing.

I have tried something along the lines of the below and while it doesn't throw any errors I am not getting the expected output.

[FunctionName("Transform")]
public static async Task<HttpResponseMessage> Import([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{

    var doc = XDocument.Load(await req.Content.ReadAsStreamAsync());
    var memoryStream = new MemoryStream();

    if (doc.Root != null)
    {
        var ns = doc.Root.GetDefaultNamespace();
        var query = from c in doc.Descendants(ns + "person")
                    select c;

        var serializer = new XmlSerializer(typeof(Person));
        var persons = new List<Person>();

        foreach (var Person in query)
        {
            var personRecord = (Person)serializer.Deserialize(person.CreateReader());
            persons.Add(personRecord);
        }


        using (var streamWriter = new StreamWriter(memoryStream))
        using (var csvWriter = new CsvWriter(streamWriter))
        {
            csvWriter.WriteRecords(persons);
            streamWriter.Flush();
            memoryStream.Flush();
        }
    }

    return new HttpResponseMessage()
    {
        StatusCode = HttpStatusCode.OK,
        Content = new StreamContent(memoryStream)
    };
}

When I debug my function locally and make a request to it via Postman I simply get a "could not load response". I was, if all worked well, expecting something like a csv output e.g.

John, Doe, 123
Mary, Jane, 456

I am wondering if the idea is good at all? At least that's what I am thinking at the moment, I just can't figure out how to do it.

Cheers

Upvotes: 2

Views: 5251

Answers (1)

Drew Marsh
Drew Marsh

Reputation: 33379

The way you're using StreamWriter is causing the MemoryStream to be disposed of. By default the StreamWriter assumes ownership of the Stream it is handed and will dispose of it when it is disposed (or GC'd).

You'll need to use the constructor overload that takes (Stream, Encoding, int, bool) where the bool is named leaveOpen and you need to set that to true. I had to double check, but there is no simpler overload of just (Stream, bool). You'd probably want to do something like:

new StreamWriter(memoryStream, Encoding.UTF8Encoding, bufferSize:8192, leaveOpen:true)

However you should really decide what encoding works best for you and what bufferSize might make the most sense for your workload.

Upvotes: 2

Related Questions