Version 4 supported
This version of Silverstripe CMS is still supported though will not receive any additional features. Go to documentation for the most recent stable version.

Import CSV Data through a Controller

You can have more customised logic and interface feedback through a custom controller. Let's create a simple upload form (which is used for MyDataObject instances). You can access it through

use SilverStripe\Forms\Form;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FileField;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\FieldsValidator;
use SilverStripe\Dev\CsvBulkLoader;
use SilverStripe\Control\Controller;

class MyController extends Controller 

    private static $allowed_actions = [

    protected $template = "BlankPage";

    public function Link($action = null) 
        return Controller::join_links('MyController', $action);

    public function Form() 
        $form = new Form(
            new FieldList(
                new FileField('CsvFile', false)
            new FieldList(
                new FormAction('doUpload', 'Upload')
            new FieldsValidator()
        return $form;

    public function doUpload($data, $form) 
        $loader = new CsvBulkLoader('MyDataObject');
        $results = $loader->load($_FILES['CsvFile']['tmp_name']);
        $messages = [];

        if($results->CreatedCount()) {
            $messages[] = sprintf('Imported %d items', $results->CreatedCount());

        if($results->UpdatedCount()) {
            $messages[] = sprintf('Updated %d items', $results->UpdatedCount());

        if($results->DeletedCount()) {
            $messages[] = sprintf('Deleted %d items', $results->DeletedCount());

        if(!$messages) {
            $messages[] = 'No changes';

        $form->sessionMessage(implode(', ', $messages), 'good');

        return $this->redirectBack();
This interface is not secured, consider using Permission::check() to limit the controller to users with certain access rights.