Golang文件上传问题:io.Reader类型不是一个有效表达式

Golang文件上传问题:io.Reader类型不是一个有效表达式 我在使用 jlaffaye/ftp 上传现有文件到 FTP 时遇到了一些问题。没有直接的“上传”命令。我找到的最接近的是 StorFrom()

ftp package - github.com/jlaffaye/ftp - Go Packages

Package ftp implements a FTP client as described in RFC 959.

但它的语法对我来说是个隐藏的秘密。我找不到任何关于如何使用它的示例。

package main

import (
	"fmt"
	"github.com/jlaffaye/ftp"
	"io"
	"os"
	"time"
)

func send2ftp(filename string) {
	c, err := ftp.Dial("ftp.test.com:21", ftp.DialWithTimeout(5*time.Second))
	if err != nil {
		fmt.Println(err)
	}

	err = c.Login("test", "test")
	if err != nil {
		fmt.Println(err)
	}

	if _, err := os.Stat(filename); err != nil {
		if os.IsNotExist(err) {
			fmt.Println("does not exist")
		}
	} else {
		fmt.Println("exists")
	}

	err = c.StorFrom(filename, io.Reader, 0)
	if err != nil {
		panic(err)
	}
}

https://play.golang.com/p/xPykHDRei-U

尝试寻找语法时出现了这个错误:

type io.Reader is not an expression

问题很简单:我如何将现有文件上传到 FTP?或者,如何使用一个字符串值在 FTP 上创建文件。


更多关于Golang文件上传问题:io.Reader类型不是一个有效表达式的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

(*ServerConn).StorFrom 期望接收一个实现了 io.Reader 接口的参数。如果你想从计算机上传文件,可以使用 os.Open 打开文件,然后将文件句柄传递给 StorFrom。完成后别忘了关闭文件!

更多关于Golang文件上传问题:io.Reader类型不是一个有效表达式的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


根据你的代码,主要问题在于StorFrom方法的第二个参数需要传入一个具体的io.Reader实例,而不是io.Reader类型本身。以下是修正后的代码示例:

package main

import (
	"fmt"
	"github.com/jlaffaye/ftp"
	"os"
	"time"
)

func send2ftp(filename string) {
	// 建立FTP连接
	c, err := ftp.Dial("ftp.test.com:21", ftp.DialWithTimeout(5*time.Second))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Quit()

	// 登录
	err = c.Login("test", "test")
	if err != nil {
		fmt.Println(err)
		return
	}

	// 检查文件是否存在
	file, err := os.Open(filename)
	if err != nil {
		if os.IsNotExist(err) {
			fmt.Println("文件不存在:", filename)
		} else {
			fmt.Println("打开文件失败:", err)
		}
		return
	}
	defer file.Close()

	// 获取文件信息用于验证
	fileInfo, err := file.Stat()
	if err != nil {
		fmt.Println("获取文件信息失败:", err)
		return
	}
	fmt.Printf("文件存在,大小: %d bytes\n", fileInfo.Size())

	// 上传文件 - 这里使用Stor方法更简单
	err = c.Stor(filename, file)
	if err != nil {
		fmt.Println("上传失败:", err)
		return
	}
	
	fmt.Println("上传成功")
}

// 如果确实需要使用StorFrom方法(支持断点续传),可以这样写:
func send2ftpWithStorFrom(filename string) {
	c, err := ftp.Dial("ftp.test.com:21", ftp.DialWithTimeout(5*time.Second))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Quit()

	err = c.Login("test", "test")
	if err != nil {
		fmt.Println(err)
		return
	}

	file, err := os.Open(filename)
	if err != nil {
		fmt.Println("打开文件失败:", err)
		return
	}
	defer file.Close()

	// StorFrom的第三个参数是偏移量(用于断点续传)
	// 0表示从文件开始上传
	err = c.StorFrom(filename, file, 0)
	if err != nil {
		fmt.Println("上传失败:", err)
		return
	}
	
	fmt.Println("上传成功")
}

// 上传字符串内容到FTP文件
func uploadStringToFTP(filename, content string) error {
	c, err := ftp.Dial("ftp.test.com:21", ftp.DialWithTimeout(5*time.Second))
	if err != nil {
		return err
	}
	defer c.Quit()

	err = c.Login("test", "test")
	if err != nil {
		return err
	}

	// 将字符串转换为io.Reader
	reader := strings.NewReader(content)
	
	// 使用Stor方法上传
	err = c.Stor(filename, reader)
	if err != nil {
		return err
	}
	
	return nil
}

func main() {
	// 上传文件
	send2ftp("example.txt")
	
	// 或者上传字符串
	// uploadStringToFTP("example.txt", "这是文件内容")
}

关键点:

  1. io.Reader是一个接口类型,不能直接作为参数值传入,需要传入实现了该接口的具体实例
  2. os.Open()返回的*os.File已经实现了io.Reader接口
  3. 对于字符串内容,可以使用strings.NewReader()创建io.Reader
  4. 对于简单的上传需求,使用Stor方法比StorFrom更直接
  5. StorFrom的第三个参数是偏移量,用于断点续传场景,从0开始表示完整上传
回到顶部