Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.
cgarciae edited this page Apr 28, 2015 · 4 revisions

GridFS

GridFS is part of Mongo and lets you store files using a similar API.

Using GridFS with Redstone Mongo Plugin

To use GridFS you just have to create a new instance, passing it a Db reference found in your dbConn

@app.Route("/upload")
newFile(@app.Attr() MongoDb dbConn)
{
    var gridFS = new GridFS (dbConn.innerConn);
    ...
}

Uploading a File

The easiest way to upload a file is through an Html <form>, if you don't mind reloading your page you could use the action and submit combo

<form enctype="multipart/form-data" method="POST" action="upload">
    Choose a file to upload: <input name="file" type="file"><br>
    <input type="submit" value="Submit">
</form>

Then you can receive it in Redstone and store it in GridFS

@app.Route("/upload", methods: const [app.POST], allowMultipartRequest: true)
newFile(@app.Attr() MongoDb dbConn, @app.Body(app.FORM) Map form) async
{
    //Get the form input field "file"
    //Redstone decodes <input type="file"> fields to an HttpBodyFileUpload for you
    HttpBodyFileUpload file = form ['file'];

    var gridFS = new GridFS (dbConn.innerConn);
    
    //Create a GridFS file with content
    var input = new Stream.fromIterable([file.content]);
    var gridIn = gridFS.createFile(input, file.filename);
    
    //Save content type (you'll need this to properly serve the file latter)
    gridIn.contentType = file.contentType.value;
    
    //Save file        
    await gridIn.save();
    
    return {'success' : true, 'id' : gridIn.id.toHexString()};
}

AJAX

If you prefer you can send the file through Dart code and avoid page reload. The easiest get it to work with Redstone is to send the whole FormElement. You'll probably use querySelector to get the <form> element and subscribe to an event. Whatever your method, you can send it to your Redstone server like this

FormElement form = YOUR_FORM_ELEMENT;
String path = "upload";

HttpRequest.request (path,
            method: "POST", 
            sendData: new FormData (form)).then ((HttpRequest req)
{
    //Handle request here
});

Serving saved files

//TODO: Add comments and explanations

@app.Route("/getfile/:fileID")
getFile(@app.Attr() MongoDb dbConn, String fileID) async
{
    GridFS gridFS = new GridFS (dbConn.innerConn);
    ObjectId objID = new ObjectId.fromHexString (fileID);
            
    GridOut gridOut = await gridFS.findOne (where.id(objID));
    //Get data
    var stream = getData (gridOut);
    
    // You'll have to set the content-type of the file
    return new shelf.Response.ok(stream, headers: { "Content-Type": gridOut.contentType }); 
    });
}

Where getData is

Stream<List<int>> getData (GridOut gridOut)
{
    StreamController<List<int>> controller = new StreamController<List<int>>();
    var n = 0;
          
    gridOut.fs.chunks.find(where.eq("files_id", gridOut.id).sortBy('n'))
    .forEach((Map chunk)
    {
        BsonBinary data = chunk["data"];
        controller.add (data.byteList);
        n++;
    })
    .then((_)
    {
        print ("$n Chunks!");
        controller.close();
    });
    
    return controller.stream;
}