Exporting files to SFTP servers directly from web browsers poses challenges due to security restrictions and the nature of the SFTP protocol. In this DevTip, we explore a practical solution that bridges this gap by using JavaScript on the frontend and Node.js on the backend to securely upload files to an SFTP server.

Introduction

Securely transferring files from web applications to remote servers via SFTP is a common requirement. However, initiating this process from a browser comes with its own set of challenges. This guide provides a step-by-step approach to implement SFTP file exports in your web application, addressing both frontend and backend considerations.

Understanding the challenge

Web browsers cannot directly communicate with SFTP servers due to the limitations of the SFTP protocol and cross-origin security policies. To overcome this limitation, we will set up a backend service that handles the SFTP communication, while the frontend collects and sends the file data to this service.

Setting up the frontend

Let's start by creating a simple HTML page that allows users to select files for export:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>SFTP File Export</title>
  </head>
  <body>
    <input type="file" id="fileInput" />
    <button id="uploadButton">Export to SFTP</button>

    <script>
      const fileInput = document.getElementById('fileInput')
      const uploadButton = document.getElementById('uploadButton')

      uploadButton.addEventListener('click', async () => {
        const file = fileInput.files[0]
        if (!file) {
          alert('Please select a file.')
          return
        }
        const formData = new FormData()
        formData.append('file', file)

        try {
          const response = await fetch('/upload', {
            method: 'POST',
            body: formData,
          })
          const data = await response.json()
          alert('File exported successfully.')
        } catch (error) {
          console.error('Error:', error)
          alert('File export failed.')
        }
      })
    </script>
  </body>
</html>

Building the backend API with Node.js

We'll use Node.js for our backend due to its excellent support for asynchronous operations and rich ecosystem of packages for handling both HTTP and SFTP protocols. We'll create a simple Express server to handle the file upload and perform the SFTP transfer.

First, initialize a new Node.js project:

mkdir sftp-upload
cd sftp-upload
npm init -y

Install the required dependencies:

npm install express multer ssh2-sftp-client dotenv
  • express for creating the server
  • multer for handling multipart/form-data (file uploads)
  • ssh2-sftp-client for SFTP communication
  • dotenv for loading environment variables

Create an index.js file:

require('dotenv').config()
const express = require('express')
const multer = require('multer')
const SftpClient = require('ssh2-sftp-client')

const app = express()
const upload = multer()

app.post('/upload', upload.single('file'), async (req, res) => {
  const sftp = new SftpClient()
  try {
    await sftp.connect({
      host: process.env.SFTP_HOST,
      port: process.env.SFTP_PORT || '22',
      username: process.env.SFTP_USERNAME,
      password: process.env.SFTP_PASSWORD,
    })

    const remotePath = `/remote/path/${req.file.originalname}`
    await sftp.put(req.file.buffer, remotePath)

    res.json({ message: 'File exported successfully.' })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: 'File export failed.' })
  } finally {
    sftp.end()
  }
})

app.listen(3000, () => {
  console.log('Server started on http://localhost:3000')
})

Create a .env file in the root of your project to store your SFTP credentials securely:

SFTP_HOST=your-sftp-host.com
SFTP_PORT=22
SFTP_USERNAME=your-username
SFTP_PASSWORD=your-password

Note: Never commit your .env file to version control. Add it to your .gitignore file.

Implementing SFTP uploads with ssh2-sftp-client

The ssh2-sftp-client package provides a simple interface for SFTP operations. It abstracts the complexities of the SFTP protocol, making it easier to perform file transfers. In our example, we use the connect() method to establish a connection to the SFTP server using the credentials from environment variables. The put() method is then used to upload the file buffer to the specified remote path.

Connecting frontend to backend

Ensure that your frontend makes a POST request to the /upload endpoint with the selected file. Since both the frontend and backend are running on the same server in this example, you shouldn't face any CORS issues. If your frontend and backend are on different domains or ports, you'll need to configure CORS accordingly.

Testing the file export functionality

Start the Node.js server:

node index.js

Open the HTML file in your browser, select a file to export, and click the "Export to SFTP" button. The file should be transferred to your SFTP server.

Security considerations

  • Authentication Credentials: Avoid hardcoding your SFTP credentials. Use environment variables or a secure configuration management system to manage sensitive information, as demonstrated using dotenv.

  • Input Validation: Implement thorough validation of uploaded files to prevent malicious content from being processed or stored. Consider validating file types, sizes, and contents before processing.

  • HTTPS: Ensure your web application uses HTTPS to encrypt data transmission between the client and server. This protects against man-in-the-middle attacks and data interception.

  • Error Handling: Implement comprehensive error handling to manage failed exports or connection issues gracefully, providing meaningful feedback to users without exposing sensitive information.

  • Rate Limiting: Consider implementing rate limiting to prevent abuse of your upload endpoint. This can help mitigate potential DoS attacks.

  • File Size Limits: Set appropriate file size limits to prevent potential denial-of-service attacks through large file uploads. Configure this both on the client-side and server-side.

  • Secure SFTP Configuration: Ensure your SFTP server is configured securely, using strong encryption algorithms and regularly updated SSH keys.

Conclusion

By bridging the frontend and backend with a simple API, we can securely export files to an SFTP server from a web application. This approach keeps sensitive operations on the server side while providing a seamless experience for users.

If you're looking for a robust solution to handle file exports and storage, consider using Transloadit. Transloadit offers an SFTP export Robot that can securely store your files on your own SFTP servers, simplifying your workflow and providing additional features like file processing and transformation.