Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File upload #48

Closed
nojaf opened this issue Apr 27, 2017 · 4 comments
Closed

File upload #48

nojaf opened this issue Apr 27, 2017 · 4 comments
Labels
feature request Request to add new functionality

Comments

@nojaf
Copy link
Contributor

nojaf commented Apr 27, 2017

It would be nice if we have some helper methods when uploading files.

Based on the aspnet core docs and this stackoverflow issue I came up with this but it the code isn't all that nice.

@dustinmoris
Copy link
Member

Hi, just to let you know I will look at your example later this evening and pick this one up next!

@dustinmoris dustinmoris added the feature request Request to add new functionality label May 14, 2017
@nojaf
Copy link
Contributor Author

nojaf commented May 14, 2017

Thanks!

@dustinmoris
Copy link
Member

Hi,

I spent some time looking into this and I created an example in the SampleApp. I have added two new HTTP POST endpoints, one for small file uploads and another for large file uploads:

POST >=>
    choose [
        route "/small-upload" >=> smallFileUploadHandler
        route "/large-upload" >=> largeFileUploadHandler ]

Then I implemented two handlers to deal with small and large file uploads:

open System.Threading
open Microsoft.AspNetCore.Http.Features

let smallFileUploadHandler =
    fun (ctx : HttpContext) ->
        async {
            return!
                (match ctx.Request.HasFormContentType with
                | false -> setStatusCode 400 >=> text "Bad request"
                | true  ->
                    ctx.Request.Form.Files
                    |> Seq.fold (fun acc file -> sprintf "%s\n%s" acc file.FileName) ""
                    |> text) ctx
        }

let largeFileUploadHandler =
    fun (ctx : HttpContext) ->
        async {
            let formFeature = ctx.Features.Get<IFormFeature>()
            let! form = formFeature.ReadFormAsync CancellationToken.None |> Async.AwaitTask
            return!
                (form.Files
                |> Seq.fold (fun acc file -> sprintf "%s\n%s" acc file.FileName) ""
                |> text) ctx
        }

I used the built in features form ASP.NET Core. For small file uploads you can directly access the files by calling ctx.Request.Form.Files, which returns an IFormCollection where each item is of type IFormFile. This matches exactly what you would get by injecting an IFormFile object into an MVC action as shown in the documented example for small file uploads.

For large file uploads there is an existing IFormFeature inside the Microsoft.AspNetCore.Http.Features namespace that you can use to stream large files. The original implementation can be found here and as you can see, it does exactly what has been described in the documentation for large file uploads.

It uses the MultipartReader to read each section and a KeyValueAccumulator to store the streamed data.

What do you think of my two examples? Is there something you would like to add or extend from a Giraffe point of view?

@nojaf
Copy link
Contributor Author

nojaf commented May 22, 2017

Hi, thanks for these examples. They are great! I had no idea that it could be this easy to process files.
I was able to reduce my own code from 90 lines to 15.

I don't think Giraffe itself needs any extension to work with files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Request to add new functionality
Projects
None yet
Development

No branches or pull requests

2 participants