Golang中如何正确将io.Reader实例作为参数传入接口函数?
错误原因
你代码中的var testIO io.Reader仅声明了一个io.Reader接口类型的变量,没有做任何赋值操作,Go语言中接口类型的零值就是nil。你将nil传入Upload方法后,方法内部执行io.Copy(formfile, r)时会尝试从nil的Reader读取数据,直接触发空指针panic,和你贴出的报错堆栈完全吻合。
解决方案
根据你的使用场景,可选择对应方案实现:
场景1:转发当前接口接收的用户上传文件到put.io
你需要先解析当前HTTP请求的multipart表单,拿到上传文件的Reader后传入即可:
func (s *server) uploadFileToPutIo(w http.ResponseWriter, r *http.Request) { tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) oauthClient := oauth2.NewClient(context.TODO(), tokenSource) client := putio.NewClient(oauthClient) // 解析multipart表单,10<<20表示最大接收10MB的上传,可按需调整 err := r.ParseMultipartForm(10 << 20) if err != nil { http.Error(w, "解析上传表单失败", http.StatusBadRequest) return } // 从表单中获取文件,file是前端上传时的字段名,可按需修改 file, header, err := r.FormFile("file") if err != nil { http.Error(w, "获取上传文件失败", http.StatusBadRequest) return } defer file.Close() // 直接把拿到的file传入Upload方法,header.Filename为用户上传的原文件名 upload, err := client.Files.Upload(context.TODO(), file, header.Filename, 0) if err != nil { log.Printf("上传到put.io失败: %v", err) http.Error(w, "上传失败", http.StatusInternalServerError) return } fmt.Println(upload.File) sendResponse(w, []byte("successful"), http.StatusOK) }
场景2:上传本地服务器上的固定文件
直接打开本地文件拿到os.File实例,它本身已经实现了io.Reader接口:
func (s *server) uploadFileToPutIo(w http.ResponseWriter, r *http.Request) { tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) oauthClient := oauth2.NewClient(context.TODO(), tokenSource) client := putio.NewClient(oauthClient) // 打开本地文件,替换为实际的本地文件路径 testIO, err := os.Open("/path/to/your/local/file") if err != nil { log.Printf("打开本地文件失败: %v", err) http.Error(w, "打开本地文件失败", http.StatusInternalServerError) return } defer testIO.Close() upload, err := client.Files.Upload(context.TODO(), testIO, "自定义上传文件名", 0) if err != nil { log.Printf("上传到put.io失败: %v", err) http.Error(w, "上传失败", http.StatusInternalServerError) return } fmt.Println(upload.File) sendResponse(w, []byte("successful"), http.StatusOK) }
注意:参考Upload方法的官方注释,该方法会把文件内容全量读取到内存中,仅适合小于150MB的文件上传,超出大小的场景需要使用分片上传方案。
内容的提问来源于stack exchange,提问作者baris
相关产品推荐
相关产品推荐

