使用Golang怎么實現(xiàn)異步上傳文件支持進(jìn)度條查詢

這篇文章將為大家詳細(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é)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

新聞名稱:使用Golang怎么實現(xiàn)異步上傳文件支持進(jìn)度條查詢
文章鏈接:http://bm7419.com/article36/igchsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、自適應(yīng)網(wǎng)站網(wǎng)站改版、網(wǎng)站維護(hù)靜態(tài)網(wǎng)站、App設(shè)計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司