D
D
Dmitry Sch2020-05-19 17:09:22
Node.js
Dmitry Sch, 2020-05-19 17:09:22

How to download files one by one from the API?

Good afternoon.
Task: download files via API to a separate folder. File content is returned in base64.

It turns out that I make the 1st request to get the entire list of current files on request for
http://site.ru/api/v1/site_files/get_list
which it returns json of the form

{
    "status": "ok",
    "data": [{
        "file_id": {
            "type": "int_unsigned_not_null",
            "edit": false,
            "value": "91064166"
        },
        "file_name": {
            "type": "str",
            "edit": true,
            "value": "main.css"
        }
    }]
}

then I make the 2nd request in a loop to get the content of each file by
http://site.ru/api/v1/site_files/get/{file_id}
getting json of the form
{
    "status": "ok",
    "data": {
        "file_id": {
            "type": "int_unsigned_not_null",
            "edit": false,
            "value": "91064166"
        },
        "file_name": {
            "type": "str",
            "edit": true,
            "value": "main.css"
        },
        "file_content": {
            "type": "blob_base64_encode",
            "edit": true,
            "value": "aHRtbCB7Zm9udC"
        }
    }
}


The code is currently written handicraft through the for of loop, how is such a task solved correctly? Use Promise? I would like to upload files one by one...
function download(done) {
  let params = new URLSearchParams();
  params.append('secret_key', SECRET_KEY);

  fetch(`${SITE}/api/v1/site_files/get_list`, {
    method: 'post',
    body:    params,
    timeout: 5000,
  })
  .then(res => res.json())
  .then(json => {
    if(json.status === `ok`) {
      console.log(`Загружен json ✔️`);  
      const dir = './download';

      if (!fs.existsSync(dir)){
        fs.mkdirSync(dir);
      }
    
      const filesArray = json.data.map((item)=>{
        return {
        file_id: item['file_id']['value'],
        file_name: item['file_name']['value'],
        }
      });
      
      return filesArray;

    } else if (json.status == `error`) {
      console.log(`Ошибка загрузки ⛔`);                         
    }
  })
  .then(array =>{
    for (const item of array) {			
      if(item.file_name.includes('css')){		
        let params = new URLSearchParams();
        params.append('secret_key', SECRET_KEY);

        fetch(`${SITE}/api/v1/site_files/get/${item.file_id}`, {
          method: 'post',
          body:    params,
          timeout: 5000,
        })
        .then(res => res.json())
        .then(json => {
          if(json.status === `ok`) {
            const binaryData = new Buffer(json.data.file_content, 'base64').toString('binary');

            fs.writeFile(`./download/${item.file_name}`, binaryData, 'binary', function(err) {
              console.log(err);
            });	
          }	
        })					
      }
    }
  })

  done();
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
Dima Pautov, 2020-05-19
@DmitrySheklein

Create an array of requests and use Promise.all this will allow you to download all your files in parallel and then process all the files

I
Igor, 2020-05-19
@loonny

And why are you doing this?

const binaryData = new Buffer(json.data.file_content, 'base64').toString('binary');

Just write directly to base64, and if you want one by one, but use writeFileSync instead of writeFile
fs.writeFileSync(`./download/${item.file_name}`, json.data.file_content, 'base64', function(err) {
  console.log(err);
});

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question