vaindil
vaindil

Reputation: 7864

Manipulating a stream inside a using statement

I'm handling uploads in .NET Core, which are passed in as IFormFile. I need to manipulate the stream to remove Exif data before I ultimately pass the file to be saved. I don't know how to handle this, however. I'm trying the code below, but it doesn't work because stream is readonly inside a using statement.

What is the correct way to do something like this?

public async Task<IActionResult> UploadImage(IFormFile image)
{
    using (var stream = new MemoryStream())
    {
        // image is IFormFile
        await image.CopyToAsync(stream);

        // doesn't work, stream is readonly
        stream = StripExif(stream);

        // save stream
    }

    return Ok();
}

public static Stream StripExif(Stream stream)
{
    stream.Seek(0, SeekOrigin.Begin);

    // remove Exif data

    return stream;
}

Upvotes: 2

Views: 900

Answers (2)

Rick Hodder
Rick Hodder

Reputation: 2252

The using is only having a problem because you are trying to assign to the using variable. You could create a new MemoryStream in StripExif, and then assign the result of StripExif to a new stream variable.

public async Task<IActionResult> UploadImage(IFormFile image)
{
    using (var stream = new MemoryStream())
    {
        // image is IFormFile
        await image.CopyToAsync(stream);

        var strippedStream = StripExif(stream);

        // save strippedStream, not stream.
    }

    return Ok();
}

public static MemoryStream StripExif(MemoryStream stream)
{
    var result = new MemoryStream();

    stream.Seek(0, SeekOrigin.Begin);

    // remove Exif data from result

    return result;
}

Updated :

public async Task<IActionResult> UploadImage(IFormFile image)
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(new MemoryStream())
    {
        // image is IFormFile
        await image.CopyToAsync(stream);

        var strippedStream = StripExif(stream, writer);

        // save strippedStream, not stream.
    }

    return Ok();
}

public static void StripExif(MemoryStream stream, StreamWriter writer)
{
    // lets assume for sake of example that removing ExIf just removes the
    // the first 10 characters of the stream
    stream.Seek(10, SeekOrigin.Begin);

    writer.Write(stream.ReadToEnd());        
}

Upvotes: 2

Servy
Servy

Reputation: 203828

StripExif is not actually creating a new Stream, rather, it's mutating the Stream passed to it, so it shouldn't be returning a Stream at all. When the caller then modifies the call to reflect that it mutates the parameter, rather than creating a new stream, the problem goes away:

public async Task<IActionResult> UploadImage(IFormFile image)
{
    using (var stream = new MemoryStream())
    {
        // image is IFormFile
        await image.CopyToAsync(stream);

        StripExif(stream);

        // save stream
    }

    return Ok();
}

public static void StripExif(Stream stream)
{
    stream.Seek(0, SeekOrigin.Begin);

    // remove Exif data
}

Upvotes: 2

Related Questions