Search code examples
filefile-upload.net-6.0minimal-apis

How to send a file to a client using a Minimal API?


I wish to send a file to an API client's GET request, but I'm getting an error:

Body was inferred but the method does not allow inferred body parameters

Here's what I've got:

Dim sPath As String = "E:\Users\Work\Desktop\20230208_220916.jpg"
oApp.MapGet("/download", Sub(Context)
                           Context.Response.ContentType = "application/octet-stream"
                           Context.Response.Headers.Add("Content-Disposition", $"attachment; filename={Path.GetFileName(sPath)}")
                           Context.Response.StatusCode = StatusCodes.Status200OK

                           Using oStream = File.OpenRead(sPath)
                             oStream.CopyToAsync(Context.Response.Body)
                           End Using
                         End Function)

I also tried this slight variation:

Dim sPath As String = "E:\Users\Work\Desktop\20230208_220916.jpg"
oApp.MapGet("/download", Function(Context)
                           Using oStream As New FileStream(sPath, FileMode.Open)
                             Return New FileStreamResult(oStream, "application/octet-stream")
                           End Using
                         End Function)

There's this answer, but it involves other types and parameters (e.g. IUserRepository, UserLogin). I have neither of these; I simply want to send the file without receiving any additional information.

Then there's this answer, but it involves controllers and therefore isn't suitable for a Minimal API. (I also tried a snippet from this answer in the above code.)

Examples abound of POSTing a file from client to server, but this is the other way 'round. I need the client to GET the file from the server. Searches consistently return results for the former, but I've not found anything for the latter (especially using a Minimal API).

How can I upload a file in response to a Minimal API client's GET request?


Solution

  • Oops, I was calling the method synchronously. The function was returning a Task instance, not the intended file.

    Once I changed it to this, the code started working:

    Dim sPath As String = "E:\Users\Work\Desktop\20230208_220916.jpg"
    Dim aData As Byte() = File.ReadAllBytes(sPath)
    
    oApp.MapGet("/download", Async Function(Context)
                               Context.Response.ContentType = "application/octet-stream"
                               Context.Response.Headers.Add("Content-Disposition", $"attachment; filename={Path.GetFileName(sPath)}")
                               Await Context.Response.Body.WriteAsync(aData)
                             End Function)