React JS: Загрузка файла на сервер

Продолжаем заметки про React JS. Сегодня речь о том, как загрузить на сервер файл вместе с кучей другой информации.

В интернете в основном описывается способ загрузки только одного файла. Поэтому себе в заметку как отправить одновременно и файл и данные. Для этого нужно использовать класс FormData, в который добавляется объект файла и данные.

В качестве примера приведу код из проекта EffectiveTours для добавления новой достопримечательности. Вся форма при заполнении сохраняется в объект sightseeing, имеющий древовидную структуру:

{
  "id" => ...
  "price" => ...
  "walkaround" => ...
  "start_time" => ...
  "names": [
      {
          "language" => ...
          "name" => ...
          "description" => ...
      },
      ...
  ]
}

Action, который отсылает данные на сервер имеет следующий вид:

saveSightseeing: function(sightseeing, photo) {
    if (!sightseeing) {
        return;
    }
    var fd = new FormData();
    if (photo !== undefined) {
        fd.append('photo', photo);
    }
    fd.append('id', sightseeing.id);
    for (var key in sightseeing) {
        if (typeof(sightseeing[key]) == "object") {
            for (var n in sightseeing[key]) {
                if (typeof(sightseeing[key][n]) == "object") {
                    for (var k in sightseeing[key][n]) {
                        fd.append(''+key+'['+n+']['+k+']', sightseeing[key][n][k]);
                    }
                } else {
                    fd.append(''+key+'['+n+']', sightseeing[key][n]);
                }
            }
        } else {
            fd.append(key, sightseeing[key]);
        }
    }
    $.ajax({
        type: "POST",
        url: Urls.LOAD_SIGHTSEEINGS,
        data: fd,
        contentType: false,
        processData: false,
        success: function(data) {
            // ...
        },
        error: function(data) {
            // ...
        }
    });
}

В начале метода происходит преобразование объекта sightseeing из древовидного в плоскую структуру и сохранение данных в экземпляре объекта FormData. (Да, данный кусок кода желательно вынести в отдельную рекурссивную функцию, но для иллюстрации метода так нагляднее). Далее заполненный экземпляр FormData отправляется AJAX запросом на сервер. Тут важно обратить внимание на два параметра:

contentType: false
processData: false

Они указывают, что не нужно обрабатывать данные перед отсылкой и не выставлять никакого ContentType.

 
comments powered by Disqus