最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

go - How to integrate azure blobstorage to an SFTP server in golang - Stack Overflow

programmeradmin0浏览0评论

I want to build a SFTP server which would take the file uploaded and directly upload it to azure blob

My SFTP server:

    listener, err := net.Listen("tcp", ":2022")
    if err != nil {
        slog.ErrorContext(ctx, "Failed to listen on port: 2022", slog.Any(constants.Error, err))
        return err
    }
    defer listener.Close()

    for {
        conn, err := listener.Accept()
        if err != nil {
            slog.ErrorContext(ctx, "Failed to accept incoming connection", slog.Any(constants.Error, err))
            return err
        }

        privateKey := os.Getenv("PRIVATE_KEY")

        serviceConfig := &ssh.ServerConfig{
            NoClientAuth: true,
        }
        signer, err := ssh.ParsePrivateKey([]byte(privateKey))
        if err != nil {
            panic(err)
        }
        serviceConfig.AddHostKey(signer)

        _, chans, req, err := ssh.NewServerConn(conn, serviceConfig)
        if err != nil {
            conn.Close()
            slog.ErrorContext(ctx, "Failed to form new handshake", slog.Any(constants.Error, err))
            return err
        }

        go ssh.DiscardRequests(req)

        for newChannel := range chans {
            if newChannel.ChannelType() != "session" {
                newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
                continue
            }

            channel, requests, err := newChannel.Accept()
            if err != nil {
                log.Fatal("could not accept channel.", err)
            }

            go func(in <-chan *ssh.Request) {
                for req := range in {
                    ok := false
                    switch req.Type {
                    case "subsystem":
                        if string(req.Payload[4:]) == "sftp" {
                            ok = true
                        }
                    }
                    req.Reply(ok, nil)
                }
            }(requests)

            server, err := sftp.NewServer(channel, []sftp.ServerOption{}...)
            if err := server.Serve(); err != nil {
                if err != io.EOF {
                    log.Fatal("sftp server completed with error:", err)
                }
            }
            server.Close()
        }
    }

My blobStorage:

type BlobStorage interface {
    Upload(ctx context.Context, key string, fileType model.FileType, fileContent []byte) error
}

// Storage represents dependency model for azure blob storage implementations.
type Storage struct {
    blobURL    string
    pipeline   pipeline.Pipeline
    credential azblob.StorageAccountCredential
}

func (storage *Storage) Upload(ctx context.Context, key string, fileContent []byte) error {

    u, _ := url.Parse(fmt.Sprintf("%s/%s", storage.blobURL, key))
    slog.InfoContext(ctx, "blob url generated", slog.String("url", u.String()))
    blockBlobURL := azblob.NewBlockBlobURL(*u, storage.pipeline)
    options := azblob.UploadToBlockBlobOptions{
        BlobHTTPHeaders: azblob.BlobHTTPHeaders{
            ContentType: "text/csv",
        },
    }

    _, err := azblob.UploadBufferToBlockBlob(ctx, fileContent, blockBlobURL, options)
    if err != nil {
        return err
    }

    slog.InfoContext(ctx, "successfully uploaded asset")

    return nil
}

Is there a way to upload the file from client to SFTP then directly upload it to blob, without actually saving it in local, and same for download as well. Is there any way to do this?

I want to build a SFTP server which would take the file uploaded and directly upload it to azure blob

My SFTP server:

    listener, err := net.Listen("tcp", ":2022")
    if err != nil {
        slog.ErrorContext(ctx, "Failed to listen on port: 2022", slog.Any(constants.Error, err))
        return err
    }
    defer listener.Close()

    for {
        conn, err := listener.Accept()
        if err != nil {
            slog.ErrorContext(ctx, "Failed to accept incoming connection", slog.Any(constants.Error, err))
            return err
        }

        privateKey := os.Getenv("PRIVATE_KEY")

        serviceConfig := &ssh.ServerConfig{
            NoClientAuth: true,
        }
        signer, err := ssh.ParsePrivateKey([]byte(privateKey))
        if err != nil {
            panic(err)
        }
        serviceConfig.AddHostKey(signer)

        _, chans, req, err := ssh.NewServerConn(conn, serviceConfig)
        if err != nil {
            conn.Close()
            slog.ErrorContext(ctx, "Failed to form new handshake", slog.Any(constants.Error, err))
            return err
        }

        go ssh.DiscardRequests(req)

        for newChannel := range chans {
            if newChannel.ChannelType() != "session" {
                newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
                continue
            }

            channel, requests, err := newChannel.Accept()
            if err != nil {
                log.Fatal("could not accept channel.", err)
            }

            go func(in <-chan *ssh.Request) {
                for req := range in {
                    ok := false
                    switch req.Type {
                    case "subsystem":
                        if string(req.Payload[4:]) == "sftp" {
                            ok = true
                        }
                    }
                    req.Reply(ok, nil)
                }
            }(requests)

            server, err := sftp.NewServer(channel, []sftp.ServerOption{}...)
            if err := server.Serve(); err != nil {
                if err != io.EOF {
                    log.Fatal("sftp server completed with error:", err)
                }
            }
            server.Close()
        }
    }

My blobStorage:

type BlobStorage interface {
    Upload(ctx context.Context, key string, fileType model.FileType, fileContent []byte) error
}

// Storage represents dependency model for azure blob storage implementations.
type Storage struct {
    blobURL    string
    pipeline   pipeline.Pipeline
    credential azblob.StorageAccountCredential
}

func (storage *Storage) Upload(ctx context.Context, key string, fileContent []byte) error {

    u, _ := url.Parse(fmt.Sprintf("%s/%s", storage.blobURL, key))
    slog.InfoContext(ctx, "blob url generated", slog.String("url", u.String()))
    blockBlobURL := azblob.NewBlockBlobURL(*u, storage.pipeline)
    options := azblob.UploadToBlockBlobOptions{
        BlobHTTPHeaders: azblob.BlobHTTPHeaders{
            ContentType: "text/csv",
        },
    }

    _, err := azblob.UploadBufferToBlockBlob(ctx, fileContent, blockBlobURL, options)
    if err != nil {
        return err
    }

    slog.InfoContext(ctx, "successfully uploaded asset")

    return nil
}

Is there a way to upload the file from client to SFTP then directly upload it to blob, without actually saving it in local, and same for download as well. Is there any way to do this?

Share Improve this question edited Jan 12 at 7:01 Steffen Ullrich 124k11 gold badges153 silver badges193 bronze badges asked Jan 12 at 4:46 Kaushal Kaushal 835 bronze badges 3
  • Refer to this link for Connect to Azure Blob Storage by using the SSH File Transfer Protocol (SFTP) – Sampath Commented Jan 13 at 9:23
  • Are you using using ssh password/key? – Sampath Commented Jan 13 at 12:12
  • @Sampath yes, i'm using ssh password and key – Kaushal Commented Jan 15 at 3:21
Add a comment  | 

1 Answer 1

Reset to default 0

How to integrate azure blobstorage to an SFTP server in golang

You can use the code below, which is currently used with the command in GoLang to upload files via an SFTP client.

In my environment, I created sftp client in the portal.

Portal:

Code:

package main

import (
    "bytes"
    "fmt"
    "os/exec"
)

func main() {
    // Prepare the SFTP command
    cmd := exec.Command("sftp", "<storage account name>.<local user name>@<storage account name>.blob.core.windows")

    // The file to upload
    file := "xx"

    // Send the `put` command using bytes.NewReader to wrap the byte slice into an io.Reader
    cmd.Stdin = bytes.NewReader([]byte(fmt.Sprintf("put %s\n", file)))

    // Execute the command and capture the output
    output, err := cmd.CombinedOutput()
    if err != nil {
        fmt.Println("Error uploading file:", err)
        return
    }

    // Print the result of the file upload
    fmt.Println("File uploaded successfully:")
    fmt.Println(string(output))
}

Output:

[email protected]'s password: 
File uploaded successfully:
Connected to venkat8912.blob.core.windows.
sftp> put /sample5.pdf
Uploading sample5.pdf to /sample5.pdf

发布评论

评论列表(0)

  1. 暂无评论