Работа с серверной частью загрузки файлов

Серверные скрипты

По сути, загрузка файлов осуществляется через Ajax. После каждого вызова метода send(), Ajax параллельно отправляет запрос методом POST. Путь к серверному скрипту указывается через свойство upload.

{view:"uploader", name:"uploader", upload:"server/upload"}

Вы можете написать свой собственный скрипт на любом доступном вам серверном языке (PHP, NodeJS и другие). Независимо от языка, скрипт должен содержать следующее:

  • место для загрузки файла
  • ответ скрипта должен соответствовать формату JS string:
    • {"status":"server"} в случае успешной операции
    • {"status":"error"} в случае отказа.

Ниже вы можете ознакомиться с решением для NodeJS

В этом примере, Модуль Busboy используется для анализа входящий данных. Когда Модуль Busboy получает файл, он вызывает событие file. Вы можете использовать это событие, чтобы поместить файл в необходимый вам каталог.

Во-первых, укажите название файла и установите кодировку MD5:

const Busboy = require("busboy");
//...
app.post(root + "/upload",(req,res)=>{
  var busboy = new Busboy({ headers: req.headers });
  var saveTo = ""; 
  var fileName = ""; 
 
  busboy.on("file", (field, file, name) => {
    fileName = path.basename(name);
    fileName = crypto.createHash("md5").update(fileName).digest("hex");
  });
  // ...
}

После этого нужно указать путь для загрузки файла:

busboy.on("file", (field, file, name) => {
  //...
  saveTo = path.join(__dirname, "uploads", "photos", fileName);
  file.pipe(fs.createWriteStream(saveTo));
});

Настройка ответа сервера

Вам необходимо настроить ответ сервера, чтобы известить пользователя о результате загрузки.

Скрипт должен вернуть строку в формате JSON, которая позже будет обработана компонентом Uploader. Виджет изменит нужные свойства в соответствующем объекте файла.

Uploader ожидает получить объект с двумя полями:

  • status ("server" если загрузка прошла успешно)
  • value с названием файла, полученным от сервера.

В примере ниже, событие finish модуля Busboy возвращает ответ сервера.

app.post(root + "/upload",(req,res)=>{
  // ...
  busboy.on("finish", function() {
    if (saveTo){
      let fileName = path.basename(saveTo);
      res.send({
        status: "server",         value: fileName         });
    }
  });
 
  return req.pipe(busboy);
}

Почему это делается таким образом? У каждого объекта файла есть свойство status, которое меняется во время загрузки:

  • client - когда файл только добавлен в Uploader, но загрузка еще не началась. Или загрузка была отменена пользователем
  • transfer - во время загрузки и до получения ответа скрипта
  • server - после загрузки, когда ответ скрипта будет "{status:'server'}"
  • error - при ошибке загрузки. Указывается, если ответ сервера будет "{'status':'error'}".

Ответ доступен в коллбэке метода send(), который принимает его в качестве параметра:

$$("uploader1").send(function(response){
  if(response)
    webix.message(response.status);
    webix.message(response.sname);
});

Related sample:  Sending on Custom Action

Загрузка нескольких файлов

В случае загрузки нескольких файлов, прямой ответ от сервера вам не подойдет, так как он содержит информацию только об одном файле.

Вместо этого, необходимо запустить цикл, который получит значения каждого файла:

$$("uploader1").send(function(){
    $$("uploader1").files.data.each(function(obj){
        var status = obj.status;
        var name = obj.name;
        if(status === "server"){
            var sname = obj.sname; //приходит из скрипта загрузки
            webix.message("Upload: "+status+" for "+ name+" stored as "+sname );
        }
        else{
            webix.message("Upload: "+status+" for "+ name);
        }
});

Related sample:  Uploader and Form Integration

Работа с файлами данных

То же самое можно сделать, если обратиться непосредственно к datastore модулю компонента через массив data:

$$("uploader1").send(function(){
    var text = f.data.pull[file_id].sname;
    webix.message("Test sname: "+ text);
});

При загрузке нескольких файлов одновременно, можно воспользоваться циклом:

for(var i in f.data.pull){
    var text = f.data.pull[i].sname;
    webix.message("Test sname: "+ text);
}

Как установить собственное название кнопки для загрузки

По умолчанию, для кнопки загрузки установлено значение "upload". Если вы хотите указать произвольное имя, вам необходимо использовать свойство inputName.

{ view:"uploader", inputName:"myFile" }
Наверх