Page 1 of 1

Download documents by passing uuid of the folder or folder path by using Rest API Node js

PostPosted:Mon Jul 10, 2023 5:17 am
by nishant8900
Code: Select all
app.get('/', async (req, res) => {
  const auth = { username: 'username', password: 'password' };
  const { path } = req.query;
  
  try {
    const result = await fileDownload(auth, path);
    console.log(result);
    // Handle the result
    res.status(200).send(result);
  } catch (err) {
    console.error(err);
    res.status(400).send({ message: err.message ? err.message : err });
  }
});

const fileDownload = async (auth, path) => {
  try {
    const result = await download(auth, path);
    console.log(result, 'file download success');
    return result;
  } catch (err) {
    throw err;
  }
};

const download = async (auth, path) => {
  try {
    const base_url = 'http://localhost/OpenKM/frontend/Download';
    //const url = 'documentdownload';
    const fullPath = `${base_url}?docPath=${encodeURIComponent(path)}`;

    const response = await axios.get(fullPath, {
      auth: {
        username: auth.username,
        password: auth.password
      },
      responseType: 'arraybuffer'
    });

    return response.data;
  } catch (err) {
    throw err;
  }
};
***This is the api i wrote***
it is downloading as a binary format, but i don't know which is correct one or not . and can you correct me this code.Please do the needful asap.

Thanks.

Re: Download documents by passing uuid of the folder or folder path by using Rest API Node js

PostPosted:Mon Jul 31, 2023 12:02 pm
by jllort
None of them, the easiest is to create an iframe on the fly like ( the browser should have an authenticated session alive with the OpenKM or must create a download link -> download with token ) :
Code: Select all
static downloadUrlWithIframe(url, sleepInMilliseconds = 0) {
    if (url) {
      // Iframe position is always created in the top left corner with high z-index to solve scroll issue in the bottom of the page
      const iframe = document.createElement('iframe');
      iframe.style.margin = '0';
      iframe.style.padding = '0';
      iframe.style.backgroundColor = 'red';
      iframe.style.height = '0';
      iframe.style.width = '0';
      iframe.style.border = '0';
      iframe.style.visibility = 'hidden'; // hidden
      iframe.style.position = 'fixed';
      iframe.style.top = '0';
      iframe.style.left = '0';
      iframe.style.zIndex = '1000'; // Same used by bootstrap contextual menus
      iframe.src = url;

      document.body.appendChild(iframe);
      if (sleepInMilliseconds > 0) {
        sleep(sleepInMilliseconds).then(() => {
          iframe.remove();
        });
      }
    }
  }
Another approach is using streamSaver, but there's a lot of problem with this approach because support of the browsers and I suggest the first:
Code: Select all
 downloadFile({ method, url, contentType, filename, params, token }) {
    // console.log('Request: [', method, '] ', url);
    // Add WritableStream support with ponyfill for browser what does not have it implemented
    if (!window.WritableStream) {
      streamSaver.WritableStream = WritableStream;
      streamSaver.TransformStream = TransformStream;
    }
    if (!method) {
      method = GET;
    }
    return fetch(url, {
      method,
      body: JSON.stringify(params),
      headers: {
        'Content-type': contentType,
        'X-Requested-App': 'kcenter',
        ...(token && { Authorization: `OKM ${token}` })
      }
    }).then(response => {
      // Error when response status != 200
      if (response.status !== 200) {
        const okmException = new OKMException('Error ' + response.status);
        throw okmException;
      } else {
        try {
          const fileStream = streamSaver.createWriteStream(filename);
          const writer = fileStream.getWriter();

          // more optimized
          if (response.body.pipeTo) {
            writer.releaseLock();
            return response.body.pipeTo(fileStream);
          }

          const reader = response.body.getReader();
          const pump = () => reader.read().then(({ value, done }) => done
            // close the stream so we stop writing
            ? writer.close()
            // Write one chunk, then get the next one
            : writer.write(value).then(pump)
          );

          // Start the reader
          pump().then(() =>
            console.log('Closed the stream, Done writing')
          );
        } catch (error) {
          throw this.buildException(error);
        }
      }
    }).catch(error => {
      throw this.buildException(error);
    });
  }