package services import ( "bytes" "crypto/tls" "eta/eta_forum_admin/utils" "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "io/ioutil" "net/http" "time" ) type OssClient interface { UploadFile(string, string, string) (string, error) GetUploadToken() (OssToken, error) } func NewOssClient() OssClient { switch utils.ObjectStorageClient { case utils.STORAGESOURCE_MINIO_NAME: return new(MinioOss) case utils.STORAGESOURCE_S3_NAME: return new(S3Oss) default: // 默认使用阿里云OSS return new(AliOss) } } // OssToken 此处为了兼容前端那边所以有重复的 type OssToken struct { AccessKeyId string SecretKeyId string RegionId string Bucketname string Endpoint string ImgHost string UseSSL string Port string //AccessKeyId string AccessKeySecret string SecurityToken string ExpiredTime string //RegionId string //Bucketname string //Endpoint string Imghost string S3ForceStyle bool S3Protocol string } type S3Oss struct{} func (m *S3Oss) UploadFile(fileName, localFile, savePath string) (resourceUrl string, err error) { defer func() { if err != nil { fmt.Println(err.Error()) } }() // 默认使用后端这个, 这里有两个配置的原因是 // 前端上传跨域问题可能会使用反向代理来解决, 这样的话同一个endpoint就会导致一端正常另一端不正常 endpoint := utils.S3BackEndpoint if endpoint == "" { endpoint = utils.S3Endpoint } accessKey := utils.S3AccessKeyId secretKey := utils.S3AccessKeySecret region := utils.S3Region bucketName := utils.S3BucketName uploadDir := utils.S3UploadDir resourceHost := utils.S3Host forceStyle := utils.S3ForceStyle hostStyle := true // 默认true, 使用`endpoint/bucket_name`这种HOST格式 if forceStyle == "false" { hostStyle = false } disableSSL := true // 默认true, 跳过SSL if utils.S3DisableSSL == "false" { disableSSL = false } //fmt.Println("disableSSL: ", disableSSL) config := &aws.Config{ Region: aws.String(region), Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""), Endpoint: aws.String(endpoint), S3ForcePathStyle: aws.Bool(hostStyle), DisableSSL: aws.Bool(disableSSL), } if disableSSL { config.HTTPClient = &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }, } } //b, _ := json.Marshal(config) //fmt.Println(string(b)) // 创建AWS会话 sess, e := session.NewSession(config) if e != nil { err = fmt.Errorf("new session err: %s", e.Error()) return } // 创建S3服务客户端 client := s3.New(sess) // 读取文件内容 fileContent, e := ioutil.ReadFile(localFile) if e != nil { err = fmt.Errorf("read file err: %s", e.Error()) return } path := savePath if savePath == "" { path = uploadDir + time.Now().Format("200601/20060102/") + fileName } putObjectInput := &s3.PutObjectInput{ Bucket: aws.String(bucketName), Key: aws.String(path), Body: bytes.NewReader(fileContent), } if utils.S3OpenAcl == "1" { putObjectInput.ACL = aws.String(s3.ObjectCannedACLPublicRead) } fmt.Printf("put object input: %+v\n", putObjectInput) _, e = client.PutObject(putObjectInput) if e != nil { err = fmt.Errorf("put object err: %s", e.Error()) return } resourceUrl = resourceHost + path if utils.ResourceProxyUrl != "" { resourceUrl = utils.ResourceProxyUrl + path } return } func (m *S3Oss) GetUploadToken() (token OssToken, err error) { token.Endpoint = utils.S3Endpoint token.AccessKeyId = utils.S3AccessKeyId token.AccessKeySecret = utils.S3AccessKeySecret token.RegionId = utils.S3Region token.Bucketname = utils.S3BucketName token.ImgHost = utils.S3Host token.Port = utils.S3EndpointPort hostStyle := true // 默认true, 使用`endpoint/bucket_name`这种HOST格式 if utils.S3ForceStyle == "false" { hostStyle = false } token.S3ForceStyle = hostStyle token.S3Protocol = utils.S3Protocol return }