273 lines
5.8 KiB
Go
273 lines
5.8 KiB
Go
package services
|
|
|
|
import (
|
|
"archive/zip"
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"netina/database"
|
|
"netina/models"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"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"
|
|
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
|
"github.com/labstack/echo/v4"
|
|
)
|
|
|
|
// ExtractZip extracts a zip file to a specified destination directory
|
|
func extractZip(zipPath string, destDir string) ([]string, error) {
|
|
r, err := zip.OpenReader(zipPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer r.Close()
|
|
|
|
var extractedFiles []string
|
|
for _, f := range r.File {
|
|
fPath := filepath.Join(destDir, f.Name)
|
|
if !strings.HasPrefix(fPath, filepath.Clean(destDir)+string(os.PathSeparator)) {
|
|
return nil, fmt.Errorf("illegal file path: %s", fPath)
|
|
}
|
|
|
|
extractedFiles = append(extractedFiles, fPath)
|
|
|
|
if f.FileInfo().IsDir() {
|
|
os.MkdirAll(fPath, os.ModePerm)
|
|
continue
|
|
}
|
|
|
|
if err := os.MkdirAll(filepath.Dir(fPath), os.ModePerm); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dstFile, err := os.OpenFile(fPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer dstFile.Close()
|
|
|
|
srcFile, err := f.Open()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer srcFile.Close()
|
|
|
|
_, err = io.Copy(dstFile, srcFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return extractedFiles, nil
|
|
}
|
|
|
|
|
|
func UpdatePanel(c echo.Context) error{
|
|
|
|
db := database.Db()
|
|
var stores []models.Store
|
|
|
|
if err := db.Where("is_removed = ?" , false).Find(&stores).Error;err != nil {
|
|
return err
|
|
}
|
|
|
|
var sess []session.Session
|
|
|
|
for _ , store := range stores {
|
|
ses , err := session.NewSession(&aws.Config{
|
|
Credentials: credentials.NewStaticCredentials(store.StorageApiKey , store.StorageSecret , ""),
|
|
Region: aws.String("ir-thr-at1"),
|
|
Endpoint: aws.String(store.StorageAddress),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sess = append(sess, *ses)
|
|
}
|
|
|
|
var svcs []s3.S3
|
|
|
|
for _ , i := range sess{
|
|
svc := s3.New(&i)
|
|
svcs = append(svcs, *svc)
|
|
}
|
|
|
|
|
|
|
|
|
|
for i:=0;i<len(svcs);i++ {
|
|
_ , err := svcs[i].HeadBucket(&s3.HeadBucketInput{
|
|
Bucket: aws.String(stores[i].StorageName),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Track cleaned storages
|
|
cleanedStorages := make(map[string]bool)
|
|
|
|
for i := 0;i<len(svcs);i++ {
|
|
if !cleanedStorages[stores[i].StorageName] {
|
|
if err := deleteAllObjects(&svcs[i] , stores[i].StorageName); err != nil {
|
|
return err
|
|
}
|
|
cleanedStorages[stores[i].StorageName] = true
|
|
}
|
|
}
|
|
|
|
|
|
|
|
dir := "./uploads"
|
|
destDir := "extractedFiles"
|
|
|
|
// Find the ZIP file in the directory
|
|
files, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var zipFilePath string
|
|
for _, file := range files {
|
|
if !file.IsDir() && strings.HasSuffix(file.Name(), ".zip") {
|
|
zipFilePath = filepath.Join(dir, file.Name())
|
|
break
|
|
}
|
|
}
|
|
|
|
if zipFilePath == "" {
|
|
fmt.Println("No ZIP file found in the directory")
|
|
return nil
|
|
}
|
|
|
|
|
|
// Extract the ZIP file
|
|
extractedFiles, err := extractZip(zipFilePath, destDir)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
|
|
// Upload extracted files to Arvan Cloud
|
|
for _, filePath := range extractedFiles {
|
|
key := filepath.Base(filePath)
|
|
for i := 0 ; i < len(stores) ; i++ {
|
|
err := uploadToArvanCloud(&sess[i] , stores[i].StorageName , filePath , key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("Successfully uploaded %s to Arvan Cloud , storage %s \n", filePath , stores[i].StorageAddress)
|
|
}
|
|
|
|
}
|
|
|
|
removeContents(dir)
|
|
removeContents("./extractedFiles")
|
|
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
|
|
func uploadToArvanCloud(sess *session.Session , bucket string , filePath string , key string)error{
|
|
|
|
|
|
file, err := ioutil.ReadFile(filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
uploder := s3manager.NewUploader(sess)
|
|
|
|
_,err = uploder.Upload(&s3manager.UploadInput{
|
|
Bucket: aws.String(bucket),
|
|
Key: aws.String(key),
|
|
Body: bytes.NewReader(file),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
func removeContents(dir string) error {
|
|
// Read the directory contents
|
|
contents, err := ioutil.ReadDir(dir)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read directory: %w", err)
|
|
}
|
|
|
|
// Iterate through each item in the directory
|
|
for _, item := range contents {
|
|
// Construct the full path of the item
|
|
itemPath := filepath.Join(dir, item.Name())
|
|
|
|
// Remove the item (file or directory)
|
|
err = os.RemoveAll(itemPath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to remove %s: %w", itemPath, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
|
|
func deleteAllObjects(svc *s3.S3, bucket string) error {
|
|
listObjectsInput := &s3.ListObjectsV2Input{
|
|
Bucket: aws.String(bucket),
|
|
}
|
|
|
|
for {
|
|
resp, err := svc.ListObjectsV2(listObjectsInput)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(resp.Contents) == 0 {
|
|
fmt.Println("No objects found in the bucket.")
|
|
break
|
|
}
|
|
|
|
var objectsToDelete []*s3.ObjectIdentifier
|
|
for _, item := range resp.Contents {
|
|
objectsToDelete = append(objectsToDelete, &s3.ObjectIdentifier{
|
|
Key: item.Key,
|
|
})
|
|
}
|
|
|
|
deleteObjectsInput := &s3.DeleteObjectsInput{
|
|
Bucket: aws.String(bucket),
|
|
Delete: &s3.Delete{
|
|
Objects: objectsToDelete,
|
|
Quiet: aws.Bool(true),
|
|
},
|
|
}
|
|
|
|
_, err = svc.DeleteObjects(deleteObjectsInput)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("Deleted %d objects from bucket %s\n", len(objectsToDelete), bucket)
|
|
|
|
if !aws.BoolValue(resp.IsTruncated) {
|
|
break
|
|
}
|
|
|
|
listObjectsInput.ContinuationToken = resp.NextContinuationToken
|
|
}
|
|
|
|
fmt.Println("All objects deleted successfully.")
|
|
|
|
return nil
|
|
} |