azure-functionsazure-blob-storagessh2

How to save file obtained by blob trigger to SFTP server with Azure Functon


I want to save file obtained by blob trigger to SFTP server with Azure Function.

module.exports = function (context, myBlob) {
    context.log("JavaScript blob trigger function processed blob \n Blob:", context.bindingData.blobTrigger, "\n Blob Size:", myBlob.length, "Bytes");
    var url = context.bindingData.uri;
    context.log(context);
    context.log(url);

    var Client = require('ssh2').Client;

    var myhost = new Client();
    myhost.on('ready',function(){

        //ready
        console.log('ready sftp...');

        //sftp
        myhost.sftp(function(err,sftp){

            //throw if error
            if(err) throw err;

            //file path
            var localfile = url;
            var remotefile = "./sftp-test/testfile.txt";

            //upload
            sftp.fastPut(localfile,remotefile,{},function(err){
                if(err){
                    console.log("upload error.");
                }else{
                    console.log("uploaded.");
                    myhost.end();
                }
            });
        });

    //connection
    }).connect({
        host: '<sftp server ipaddress>',
        port:22,
        username:'sftpuser',
        privateKey:require('fs').readFileSync('D:/home/site/wwwroot/verification-BlobStorage-sftp/.ssh/id_rsa'),
    }); 
};

I tried to create new file on target blob storage.
After that, start function by blob trigger. The result log is:

2020-01-06T06:23:04  Welcome, you are now connected to log-streaming service. The default timeout is 2 hours. Change the timeout with the App Setting SCM_LOGSTREAM_TIMEOUT (in seconds). 
2020-01-06T06:24:04  No new trace in the past 1 min(s).
2020-01-06T06:25:02.718 [Information] Executing 'Functions.verification-BlobStorage-sftp2' (Reason='New blob detected: verificationblobstorage/test0106.test', Id=0d5dda28-8913-4660-bcdd-82a6e78c8fec)
2020-01-06T06:25:10.534 [Information] JavaScript blob trigger function processed blob 
 Blob: verificationblobstorage/test0106.test 
 Blob Size: 23 Bytes
2020-01-06T06:25:10.553 [Information] InvocationContext {
  invocationId: '0d5dda28-8913-4660-bcdd-82a6e78c8fec',
  traceContext:
   { traceparent: '00-6a5c700bee92534599b540ce4fb6078f-e1e6436e28ea684d-00',
     tracestate: '',
     attributes: { OperationName: 'verification-BlobStorage-sftp2' } },
  executionContext:
   { invocationId: '0d5dda28-8913-4660-bcdd-82a6e78c8fec',
     functionName: 'verification-BlobStorage-sftp2',
     functionDirectory: 'D:\\home\\site\\wwwroot\\verification-BlobStorage-sftp2' },
  bindings:
   { myBlob:
      <Buffer 74 65 73 74 0d 0a 74 65 73 74 0d 0a 74 65 73 74 31 31 31 31 31 0d 0a> },
  log:
   { [Function]
     error: [Function: error],
     warn: [Function: warn],
     info: [Function: info],
     verbose: [Function: verbose] },
  bindingData:
   { invocationId: '0d5dda28-8913-4660-bcdd-82a6e78c8fec',
     blobTrigger: '<myblobpath>',
     uri:
      'https://<myblobpath>',
---Omitted---

No more logs were displayed.

It seems that I can get blob file when checked the log.
Why cannot save file on SFTP server?


Solution

  • According to my test, we can use the SDK ssh2-sftp-clientto upload file to SFTP server. For more details about the SDK, please refer to the document.

    For example

    const Client = require('ssh2-sftp-client');
    
    module.exports = async function (context, myBlob) {
       // get blob name
        var strs =context.bindingData.blobTrigger.split("/")
    
        var sftp  = new Client();
        var data = context.bindings.myBlob; // get blob content as buffer
        var remote = "/home/jimtest/"+strs[1];
        context.log(remote);
        sftp.connect({
            host: '< string Hostname or IP of server>',
            port: '22',
            username: ' ',
            password: ' '
          }).then(() => {
            return sftp.put(data, remote);
          })
          .then(() => {
            return sftp.end();
          })
          .catch(err => {
            context.log(err.message);
          });
         context.done()
    };