您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關使用Golang怎么實現異步上傳文件支持進度條查詢,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
ZIP壓縮包解壓
使用golang自帶的 "archive/zip" 包解壓。
func decompressZip(filePath, dest string) (string, string, error) { var csvName string imageFolder := path.Base(filePath) ext := path.Ext(filePath) folderName := strings.TrimSuffix(imageFolder, ext) src, err := os.Open(filePath) if err != nil { return "", "", err } defer src.Close() zipFile, err := zip.OpenReader(src.Name()) if err != nil { return "", "", err } defer zipFile.Close() err = os.MkdirAll(path.Join(dest, folderName), os.ModePerm) for _, innerFile := range zipFile.File { info := innerFile.FileInfo() if info.IsDir() { continue } dst, err := os.Create(path.Join(dest, folderName, info.Name())) if err != nil { fmt.Println(err.Error()) continue } src, err := innerFile.Open() if err != nil { fmt.Println(err.Error()) continue } io.Copy(dst, src) } destPath, err := ioutil.ReadDir(path.Join(dest, folderName)) if err != nil { return "", "", err } for _, v := range destPath { if path.Ext(v.Name()) == ".csv" { csvName = path.Join(dest, folderName, v.Name()) } } return folderName, csvName, nil }
在這個解壓的過程中,壓縮包的樹結構只能到2層
import.zip ┝┅┅import.csv ┖┅┅images
在解壓后,所有的文件都會在同一個目錄下,既images中的圖片會變成和.csv文件同級
驗證csv文件編碼格式是否為UTF-8
func ValidUTF8(buf []byte) bool { nBytes := 0 for i := 0; i < len(buf); i++ { if nBytes == 0 { if (buf[i] & 0x80) != 0 { //與操作之后不為0,說明首位為1 for (buf[i] & 0x80) != 0 { buf[i] <<= 1 //左移一位 nBytes++ //記錄字符共占幾個字節 } if nBytes < 2 || nBytes > 6 { //因為UTF8編碼單字符最多不超過6個字節 return false } nBytes-- //減掉首字節的一個計數 } } else { //處理多字節字符 if buf[i]&0xc0 != 0x80 { //判斷多字節后面的字節是否是10開頭 return false } nBytes-- } } return nBytes == 0 }
后續支持utf-8轉碼
這個utf8編碼判斷方法是網上down下來的,后續優化一下
主邏輯
type LineWrong struct { LineNumber int64 `json:"line_number"` Msg string `json:"msg"` } func Import(/*自定義參數*/){ // decompress zip file to destination address folder, csvName, err := Decompress(path.Join(constant.FolderPrefix, req.FilePath), dest) if err != nil { fmt.Println(err.Error()) } // check if the file encoding is utf8 b, err := ioutil.ReadFile(csvName) if err != nil { fmt.Println(err.Error()) } if !utils.ValidUTF8(b) { fmt.Println(errors.New("數據編碼錯誤,請使用utf-8格式csv!")) } // create goroutine to analysis data into mongodb var wg sync.WaitGroup wg.Add(1) // used to interrupt goroutine resultChan := make(chan error) // used to record wrong row in csv lW := make(chan []LineWrong) go func(ctx *gin.Context, Name, csvPath, dir, folder string) { defer wg.Done() tidT, ciT, lwT, err := importCsv(ctx, Name, csvPath, dir, folder) resultChan <- err if err != nil { fmt.Println(err.Error()) } lW <- lwT if len(lwT) == 0 { importClassData(ctx, tidT, ciT) } }(ctx, req.Name, csvName, dest, folder) err = <-resultChan lineWrong := <-lW close(lW) ··· } // pre-analysis data in csv and through wrong data with line numbers and information func importCsv()(){ ··· } // analysis data again and save data into mongodb, if is there any error,through them same as import() func importClassData()(){ ··· conn, err := connect() if err != nil { return err } defer conn.Close() conn.Do("hset", taskId, "task_id", (curLine*100)/totalLines) ··· }
將錯誤信息以channel接收,使用 package "sync" 的 sync.WaitGroup 控制異步協程。在入庫的過程中,將當前的進度存入redis。
查詢進度接口
func QueryImport()(){ conn, err := connect() if err != nil { return nil, err } defer conn.Close() progress, _ := conn.Do("hget", key, field) if pro, ok := progress.([]uint8); ok { ba := []byte{} for _, b := range pro { ba = append(ba, byte(b)) } progress,_ = strconv.Atoi(string(ba)) } return progress }
關于使用Golang怎么實現異步上傳文件支持進度條查詢就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。