這篇文章將為大家詳細(xì)講解有關(guān)使用Golang怎么實現(xiàn)異步上傳文件支持進(jìn)度條查詢,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
綠春網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),綠春網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為綠春成百上千提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)公司要多少錢,請找那個售后服務(wù)好的綠春做網(wǎng)站的公司定做!
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 }
在這個解壓的過程中,壓縮包的樹結(jié)構(gòu)只能到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++ //記錄字符共占幾個字節(jié) } if nBytes < 2 || nBytes > 6 { //因為UTF8編碼單字符最多不超過6個字節(jié) return false } nBytes-- //減掉首字節(jié)的一個計數(shù) } } else { //處理多字節(jié)字符 if buf[i]&0xc0 != 0x80 { //判斷多字節(jié)后面的字節(jié)是否是10開頭 return false } nBytes-- } } return nBytes == 0 }
后續(xù)支持utf-8轉(zhuǎn)碼
這個utf8編碼判斷方法是網(wǎng)上down下來的,后續(xù)優(yōu)化一下
主邏輯
type LineWrong struct { LineNumber int64 `json:"line_number"` Msg string `json:"msg"` } func Import(/*自定義參數(shù)*/){ // 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("數(shù)據(jù)編碼錯誤,請使用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 控制異步協(xié)程。在入庫的過程中,將當(dāng)前的進(jìn)度存入redis。
查詢進(jìn)度接口
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 }
關(guān)于使用Golang怎么實現(xiàn)異步上傳文件支持進(jìn)度條查詢就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。