Skip to content

Commit

Permalink
add aliyun oss
Browse files Browse the repository at this point in the history
  • Loading branch information
myussufz committed Apr 20, 2019
1 parent c36fbbe commit 40293a0
Show file tree
Hide file tree
Showing 10 changed files with 681 additions and 75 deletions.
1 change: 1 addition & 0 deletions adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ type Adapter interface {
}

var _ Adapter = &GCSAdapter{}
var _ Adapter = &AliyunAdapter{}
196 changes: 196 additions & 0 deletions aliyun_adapter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package storage

import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
"strings"
"time"

oss "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

// AliyunAdapter : The adapter empty because they do not have any data to share for now
type AliyunAdapter struct {
Endpoint string
AccessKeyID string
AccessKeySecret string
}

// UploadFile : Upload file to the bucket
func (adapter *AliyunAdapter) UploadFile(file *multipart.FileHeader, bucket, filename string) (string, error) {
var reader io.Reader
name := ""

fileExt := strings.ToLower(strings.Split(file.Header.Get("Content-Type"), "/")[1])

if ext, isExist := extensionMapper[fileExt]; isExist {
name = fmt.Sprintf("%s.%s", filename, ext)
} else {
name = fmt.Sprintf("%s.%s", filename, fileExt)
}

src, err := file.Open()
if err != nil {
return "", err
}

defer src.Close()
reader = src

fileURL, err := adapter.UploadReader(bucket, name, reader, strings.ToLower(fileExt))
if err != nil {
return "", err
}

return fileURL, nil
}

// DeleteFileUsingURL : Delete file from the bucket using url
func (adapter *AliyunAdapter) DeleteFileUsingURL(bucket, fileURL string) error {
storageClient, err := adapter.getClient()
if err != nil {
return err
}

object, err := storageClient.Bucket(bucket)
if err != nil {
return err
}

filepath := adapter.getFilePathFromURL(bucket, fileURL)

return object.DeleteObject(filepath)
}

// TemporaryServingFile : TemporaryServingFile file serving
func (adapter *AliyunAdapter) TemporaryServingFile(bucket, fileURL string, expiredDateTime time.Time, aliClient interface{}) (string, error) {
storageClient, err := adapter.getClient()
if err != nil {
return "", err
}

object, err := storageClient.Bucket(bucket)
if err != nil {
return "", err
}

filepath := adapter.getFilePathFromURL(bucket, fileURL)

url, err := object.SignURL(filepath, http.MethodGet, int64(expiredDateTime.UTC().Sub(time.Now().UTC()).Seconds()))
if err != nil {
return "", err
}

return url, nil
}

// UploadReader :
func (adapter *AliyunAdapter) UploadReader(bucket, filename string, reader io.Reader, contentType string) (string, error) {
storageClient, err := adapter.getClient()
if err != nil {
return "", err
}

object, err := storageClient.Bucket(bucket)
if err != nil {
return "", err
}

options := make([]oss.Option, 0)
if contentType == "" {
options = aliyunContentTypeAny(filename)
} else {
contentFunc, isExist := aliyunContentTypeMapper[contentType]
if !isExist {
return "", fmt.Errorf("Content type %s does not supported", contentType)
}
options = contentFunc(filename)
}

if err := object.PutObject(filename, reader, options...); err != nil {
msg := fmt.Sprintf("Could not write file: %v", err)
return "", errors.New(msg)
}

return getAliyunFileURL(adapter.Endpoint, bucket, filename), nil
}

// ReadFile :
func (adapter *AliyunAdapter) ReadFile(bucket, path string) ([]byte, error) {
storageClient, err := adapter.getClient()
if err != nil {
return nil, err
}

object, err := storageClient.Bucket(bucket)
if err != nil {
return nil, err
}

rc, err := object.GetObject(path)
defer rc.Close()
slurp, err := ioutil.ReadAll(rc)
if err != nil {
return nil, err
}
return slurp, nil
}

// UploadBuffer :
func (adapter *AliyunAdapter) UploadBuffer(bucket, filename string, contentType string) (*Buffer, error) {
buf := new(Buffer)
buf.adapter = ALIYUN

storageClient, err := adapter.getClient()
if err != nil {
return nil, err
}

object, err := storageClient.Bucket(bucket)
if err != nil {
return nil, err
}

contentFunc, isExist := aliyunContentTypeMapper[contentType]
if !isExist {
return nil, fmt.Errorf("Content type %s does not supported", contentType)
}
options := contentFunc(filename)

buffer := new(bytes.Buffer)

// delete the object before append
object.DeleteObject(filename)

position, err := object.AppendObject(filename, buffer, buf.position, options...)
if err != nil {
log.Println("error: ", err)
return nil, err
}
buf.position = position

buf.position = position
buf.object = object
buf.filename = filename
buf.bucket = bucket
buf.endpoint = adapter.Endpoint
return buf, nil
}

func (adapter *AliyunAdapter) getClient() (*oss.Client, error) {
return oss.New(adapter.Endpoint, adapter.AccessKeyID, adapter.AccessKeySecret)
}

func getAliyunFileURL(endpoint, bucket string, filename string) string {
return fmt.Sprintf("https://%s.%s/%s", bucket, endpoint, filename)
}

func (adapter *AliyunAdapter) getFilePathFromURL(bucket, fileURL string) string {
return strings.Replace(fileURL, fmt.Sprintf("https://%s.%s/", bucket, adapter.Endpoint), "", -1)
}
111 changes: 111 additions & 0 deletions aliyun_content_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package storage

import (
"fmt"
"strings"

"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

var aliyunContentTypeMapper = map[string]func(filename string) []oss.Option{
ContentTypeCSV: aliyunContentTypeCSV,
ContentTypePNG: aliyunContentTypePNG,
ContentTypeJPEG: aliyunContentTypeJPEG,
ContentTypePDF: aliyunContentTypePDF,
ContentTypeZip: aliyunContentTypeZip,
ContentTypeAPK: aliyunContentTypeApk,
ContentTypeHTML: aliyunContentTypeHTML,
ContentTypeCSS: aliyunContentTypeCSS,
ContentTypeJS: aliyunContentTypeJS,
ContentTypeExcel: aliyunContentTypeExcel,
}

func aliyunContentTypeZip(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("application/zip"))
options = append(options, oss.ContentDisposition(fmt.Sprintf("attachment;filename=%s", filename)))

return options
}

func aliyunContentTypeCSV(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("text/csv"))
options = append(options, oss.ContentDisposition(fmt.Sprintf("attachment;filename=%s", filename)))

return options
}

func aliyunContentTypePNG(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("image/png"))

return options
}

func aliyunContentTypeJPEG(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("image/jpeg"))

return options
}

func aliyunContentTypePDF(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("application/pdf"))

return options
}

func aliyunContentTypeAny(filename string) []oss.Option {
filenameArr := strings.Split(filename, ".")
fileExtension := strings.TrimSpace(filenameArr[len(filenameArr)-1])

options := make([]oss.Option, 0)
options = append(options, oss.ContentDisposition(fmt.Sprintf("attachment;filename=%s", filename)))

contentFunc, isExist := aliyunContentTypeMapper[fileExtension]
if isExist {
o := contentFunc(filename)
options = append(options, o...)
}

return options
}

func aliyunContentTypeApk(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("application/vnd.android.package-archive"))
options = append(options, oss.ContentDisposition(fmt.Sprintf("attachment;filename=%s", filename)))

return options
}

func aliyunContentTypeHTML(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("text/html"))

return options
}

func aliyunContentTypeCSS(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("text/css"))

return options
}

func aliyunContentTypeJS(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("application/javascript"))

return options
}

func aliyunContentTypeExcel(filename string) []oss.Option {
options := make([]oss.Option, 0)
options = append(options, oss.ContentType("application/vnd.ms-excel"))
options = append(options, oss.ContentDisposition(fmt.Sprintf("attachment;filename=%s", filename)))

return options
}
Loading

0 comments on commit 40293a0

Please sign in to comment.