婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識(shí)庫 > golang實(shí)現(xiàn)的文件上傳下載小工具

golang實(shí)現(xiàn)的文件上傳下載小工具

熱門標(biāo)簽:鄭州智能語音電銷機(jī)器人價(jià)格 仙桃400電話辦理 寧波語音外呼系統(tǒng)公司 宿遷便宜外呼系統(tǒng)代理商 湛江crm外呼系統(tǒng)排名 地圖標(biāo)注免費(fèi)定制店 重慶慶云企業(yè)400電話到哪申請(qǐng) 上海極信防封電銷卡價(jià)格 不封卡外呼系統(tǒng)

前言

雖然現(xiàn)在文件上傳下載工具多如牛毛,比如http、ftp、sftp、scp等方案都可以用于文件傳輸,但都是需要安裝服務(wù)器甚至客戶端。
有一種場景是我只需要臨時(shí)上傳或下載一個(gè)文件,完了就不用服務(wù)器運(yùn)行了,如果使用那些文件傳輸工具,不光安裝麻煩,開啟關(guān)閉也惱火額。
因此才想搞小工具,不過Python愛好者可以用python -m http.server 8080 --bind 192.168.1.100開啟文件服務(wù)器,對(duì)我來說還是麻煩。
已經(jīng)上傳到【Github】,隨意鑒賞。

源碼鑒賞

模擬一個(gè)http服務(wù)器,通過curl和wget命令作為客戶端實(shí)現(xiàn)文件的上傳下載功能。
只是實(shí)現(xiàn)一個(gè)小工具,所以沒必要使用http庫了,我也試過用http庫來完成相同的功能,發(fā)現(xiàn)很多東西都用不上。
上傳和下載文件加入了進(jìn)度顯示,方便知道上傳和下載進(jìn)度。本來想實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能,但比較懶,不想弄,原理很簡單。
想想還是把認(rèn)證授權(quán)加上去,不然太不安全了,命令行更新了使用用戶名和密碼方式的上傳和下載。

package main
 
import (
  "bufio"
  "encoding/base64"
  "errors"
  "fmt"
  "io"
  "net"
  "net/url"
  "os"
  "path/filepath"
  "strconv"
  "strings"
  "unsafe"
)
 
func main() {
  if len(os.Args) != 3 {
    fmt.Printf(`usage: %s ip:port user:pass
 
get file:
 wget --auth-no-challenge --user=user --password=pass --content-disposition "http://ip:port?/home/tmp.txt"
 curl -u user:pass -OJ "http://ip:port?/home/tmp.txt"
post file:
 wget -qO - --auth-no-challenge --user=user --password=pass --post-file=C:\tmp.txt "http://ip:port?/home/tmp.txt"
 curl -u user:pass --data-binary @C:\tmp.txt "http://ip:port?/home/tmp.txt"
`, os.Args[0])
    return
  }
  addr, err := net.ResolveTCPAddr("tcp", os.Args[1])
  if err != nil {
    panic(err)
  }
  ser, err := net.ListenTCP("tcp", addr)
  if err != nil {
    panic(err)
  }
 
  fmt.Printf("Listen: [%s]\n", addr)
  authStr = "Basic " + base64.StdEncoding.EncodeToString([]byte(os.Args[2]))
  for {
    ln, err := ser.AcceptTCP()
    if err != nil {
      panic(err)
    }
    go func(l *net.TCPConn) {
      err := handleFile(l)
      if err != nil {
        respData(l, err.Error())
      }
      l.Close()
    }(ln)
  }
}
 
const (
  maxMemory = 10  20 // 緩存10MB
  respMsg  = "HTTP/1.1 200 OK\r\nContent-Type:text/plain;charset=utf-8\r\nContent-Disposition:attachment;filename=resp.txt\r\nContent-Length:%d\r\n\r\n%s"
  getHeader = "HTTP/1.1 200 OK\r\nContent-Type:application/octet-stream\r\nContent-Disposition:attachment;filename=%s\r\nContent-Length:%d\r\nContent-Transfer-Encoding:binary\r\n\r\n"
)
 
var authStr string // 授權(quán)信息
 
func respData(w io.Writer, data string) {
  msg := data + "\r\n"
  fmt.Fprintf(w, respMsg, len(msg), msg)
}
 
func handleFile(l *net.TCPConn) error {
  br := bufio.NewReaderSize(l, maxMemory)
  method, path, length, err := getHeaderMsg(br)
  if err != nil {
    return err
  }
  fmt.Printf("[%s - %s - %d]\n", method, path, length)
 
  if method == "GET" {
    return httpGetFile(path, l, length)
  }
  err = httpPostFile(path, br, length)
  if err != nil {
    return err
  }
  respData(l, "post ok")
  return nil
}
 
// 內(nèi)存復(fù)用,更快速,省內(nèi)存
func bytesToString(b []byte) string {
  return *(*string)(unsafe.Pointer(b))
}
 
func getHeaderMsg(r *bufio.Reader) (string, string, int64, error) {
  // 讀取第一行,提取有用信息
  line, _, err := r.ReadLine()
  if err != nil {
    return "", "", 0, err
  }
  header := strings.Fields(bytesToString(line))
  if len(header)  3 { // 首行至少3列數(shù)據(jù)
    return "", "", 0, errors.New("header error")
  }
  method, path := header[0], ""
 
  s := strings.Index(header[1], "?")
  if s >= 0 {
    path, _ = url.QueryUnescape(header[1][s+1:])
  }
  if path == "" { // ?號(hào)后面就是文件路徑,需要解碼url一下
    return "", "", 0, errors.New("path error")
  }
 
  var length int64
  if method == "GET" {
    fi, err := os.Stat(path)
    if err != nil {
      return "", "", 0, err
    }
    length = fi.Size() // GET請(qǐng)求提前得到文件大小
  } else if method != "POST" {
    return "", "", 0, errors.New(method + " not support")
  }
 
  var authCheck string
  for {
    line, _, err = r.ReadLine()
    if err != nil {
      return "", "", 0, err
    }
    if len(line) == 0 {
      break // 遇到空行,之后為請(qǐng)求體
    }
    header = strings.Split(bytesToString(line), ":")
    if len(header) == 2 { // 頭部[key: val]解析
      header[0] = strings.ToLower(strings.TrimSpace(header[0]))
      header[1] = strings.TrimSpace(header[1])
      if method == "POST"  header[0] == "content-length" {
        length, _ = strconv.ParseInt(header[1], 10, 64)
      } else if header[0] == "authorization" {
        authCheck = header[1]
      }
    }
  }
  if authCheck != authStr {
    return "", "", 0, errors.New("authorization error")
  }
  return method, path, length, nil
}
 
func httpPostFile(path string, r io.Reader, length int64) error {
  fw, err := os.Create(path)
  if err != nil {
    return err
  }
  defer fw.Close()
  pr := newProgress(r, length)
  _, err = io.CopyN(fw, pr, length)
  pr.Close()
  return err
}
 
func httpGetFile(path string, w io.Writer, size int64) error {
  fr, err := os.Open(path)
  if err != nil {
    return err
  }
  defer fr.Close()
  fmt.Fprintf(w, getHeader, filepath.Base(path), size)
  pr := newProgress(fr, size)
  _, err = io.Copy(w, pr)
  pr.Close()
  return err
}
 
type progress struct {
  r  io.Reader
  cnt int64
  rate chan int64
}
 
func newProgress(r io.Reader, size int64) io.ReadCloser {
  p := progress{r: r, rate: make(chan int64)}
  // 之所以這樣做進(jìn)度,是因?yàn)榇蛴『男阅?因此在協(xié)程中打印進(jìn)度
  // 在處理數(shù)據(jù)中用非阻塞方式往chan中傳處理字節(jié)數(shù)
  go func(rate -chan int64, all int64) {
    for cur := range rate {
      fmt.Printf("\rhandle:%4d%%", cur*100/all)
    }
    fmt.Printf("\rhandle: 100%%\r\n\r\n")
  }(p.rate, size)
  return p
}
 
func (p *progress) Read(b []byte) (int, error) {
  n, err := p.r.Read(b)
  p.cnt += int64(n)
  select { // 非阻塞方式往chan中寫數(shù)據(jù)
  case p.rate - p.cnt:
  default:
  }
  return n, err
}
 
func (p *progress) Close() error {
  close(p.rate) // 關(guān)閉chan,通知打印協(xié)程退出
  return nil
}

食用方法

執(zhí)行UpDownFile-h可以查看幫助文檔,里面有wget和curl上傳和下載文件的命令,方便忘記命令的時(shí)候copy一下下。
工具雖小,但確實(shí)解決了我個(gè)人的臨時(shí)上傳下載文件需求,再也不用到處安裝各種服務(wù)器咯,爽爽噠。

usage: UpDownFile ip:port
 
get file:
 wget --auth-no-challenge --user=user --password=pass --content-disposition "http://ip:port?/home/tmp.txt"
 curl -u user:pass -OJ "http://ip:port?/home/tmp.txt"
post file:
 wget -qO - --auth-no-challenge --user=user --password=pass --post-file=C:\tmp.txt "http://ip:port?/home/tmp.txt"
 curl -u user:pass --data-binary @C:\tmp.txt "http://ip:port?/home/tmp.txt"

以上就是golang實(shí)現(xiàn)的文件上傳下載小工具的詳細(xì)內(nèi)容,更多關(guān)于golang實(shí)現(xiàn)文件上傳下載的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • golang語言實(shí)現(xiàn)的文件上傳與文件下載功能示例
  • Golang實(shí)現(xiàn)異步上傳文件支持進(jìn)度條查詢的方法
  • Golang+Android基于HttpURLConnection實(shí)現(xiàn)的文件上傳功能示例
  • golang簡單獲取上傳文件大小的實(shí)現(xiàn)代碼
  • Golang實(shí)現(xiàn)http文件上傳小功能的案例

標(biāo)簽:安康 海南 物業(yè)服務(wù) 遼寧 西雙版納 電子產(chǎn)品 青海 儋州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《golang實(shí)現(xiàn)的文件上傳下載小工具》,本文關(guān)鍵詞  golang,實(shí)現(xiàn),的,文件,上傳下載,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《golang實(shí)現(xiàn)的文件上傳下載小工具》相關(guān)的同類信息!
  • 本頁收集關(guān)于golang實(shí)現(xiàn)的文件上傳下載小工具的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    aaa国产一区| 欧美三级韩国三级日本三斤| 欧美一区二区三区成人| 国产激情视频一区二区三区欧美| 丝袜美腿亚洲一区| 福利一区福利二区| 福利91精品一区二区三区| 免费久久99精品国产| av福利精品导航| www.日韩大片| 精品久久久久香蕉网| 91久久精品国产91性色tv | 国产乱码精品一区二区三 | 欧美一卡在线观看| 欧美怡红院视频| 91久久一区二区| 91麻豆高清视频| 99久久综合狠狠综合久久| 国产精品电影一区二区| 久久夜色精品一区| 日韩精品中午字幕| 日韩欧美国产一区二区在线播放| 欧美日韩视频在线一区二区| 欧美视频一二三区| 欧美三级电影网| 日韩一区二区在线观看视频播放 | 日韩欧美综合在线| 337p亚洲精品色噜噜狠狠| 欧美日韩国产三级| 日韩一级大片在线观看| 久久综合av免费| 国产婷婷色一区二区三区四区| 久久久久久久久久久黄色| 国产欧美日韩麻豆91| 亚洲图片你懂的| 亚洲国产精品久久人人爱| 香蕉久久夜色精品国产使用方法 | 色婷婷精品久久二区二区蜜臀av | 中文字幕乱码一区二区免费| 中文字幕第一区第二区| 国产精品福利一区二区三区| 一区二区三区久久| 亚洲成人高清在线| 黄一区二区三区| 成熟亚洲日本毛茸茸凸凹| 91麻豆免费视频| 日韩一级片网址| 中文字幕一区二区三区蜜月| 久久精品国产精品亚洲红杏| 日韩视频国产视频| 日本一区二区三区四区在线视频| 一区二区三区在线观看视频| 2023国产精华国产精品| 91国产免费观看| 色天天综合色天天久久| 欧美三级电影网站| 免费av成人在线| 精品欧美一区二区三区精品久久| 亚洲裸体在线观看| 粉嫩在线一区二区三区视频| 91丨九色丨蝌蚪富婆spa| 日韩精品一区第一页| 国产乱码精品一品二品| 91在线视频播放地址| 国产成人自拍网| 日韩精品一区二区三区在线播放| 亚洲国产欧美在线| 成人一区二区三区视频在线观看| 成人动漫av在线| 制服丝袜日韩国产| 久久综合九色综合欧美就去吻| 国产精品久久三| 9人人澡人人爽人人精品| 中文字幕av在线一区二区三区| 国产一区二区h| 欧美精品日日鲁夜夜添| 久久99日本精品| 欧日韩精品视频| 亚洲精品中文在线观看| 精品视频999| 性欧美疯狂xxxxbbbb| 91在线观看一区二区| 欧美中文一区二区三区| 久久久久高清精品| 97精品国产97久久久久久久久久久久| 毛片av一区二区| 久久这里只有精品视频网| 国产精品美女久久久久久久| 捆绑调教一区二区三区| 欧美色倩网站大全免费| 亚洲福利视频三区| 99v久久综合狠狠综合久久| 一区二区三区免费看视频| 播五月开心婷婷综合| 亚洲午夜一二三区视频| 色天天综合色天天久久| 亚洲免费在线电影| 91精品国产综合久久婷婷香蕉 | 欧美一区二区在线视频| 婷婷激情综合网| 欧美三级三级三级| 狠狠色狠狠色综合| 一区二区三区不卡视频| 日韩欧美的一区| 国产成人精品免费一区二区| 亚洲自拍偷拍av| 国产日韩欧美精品在线| 91国偷自产一区二区使用方法| 五月天视频一区| 在线播放中文字幕一区| 欧洲一区在线电影| 国产99久久久国产精品免费看| 亚洲女人小视频在线观看| 欧美一级一区二区| 91久久人澡人人添人人爽欧美| 91麻豆精品国产91久久久使用方法| 日本va欧美va精品发布| 7777女厕盗摄久久久| 色老汉一区二区三区| 欧美性色黄大片| www.成人网.com| 欧美性生活大片视频| 高清免费成人av| 久久精品国产一区二区| 午夜精品免费在线观看| 欧美激情一区二区在线| 美洲天堂一区二卡三卡四卡视频| 日本一区二区三区dvd视频在线| 国产成人超碰人人澡人人澡| 狠狠狠色丁香婷婷综合激情| 久久久久9999亚洲精品| 成人av中文字幕| 亚洲视频一二三| 国产不卡在线视频| 亚洲综合在线观看视频| 欧美在线免费观看亚洲| 精品一区二区三区香蕉蜜桃| 久久久久久麻豆| 欧美亚洲一区三区| 五月综合激情网| 日韩一区和二区| 91网站最新网址| 乱中年女人伦av一区二区| 国产精品动漫网站| 国产精品成人在线观看| 日韩欧美另类在线| 国产一区二区三区黄视频| 色哟哟国产精品| 午夜久久久影院| 久久久久99精品国产片| 欧美性高清videossexo| 国产一区视频导航| 亚洲成人动漫精品| 中文字幕国产一区| 欧美揉bbbbb揉bbbbb| 波多野洁衣一区| 蜜桃视频免费观看一区| 亚洲精品国产一区二区精华液 | 日本久久一区二区三区| 国产在线精品国自产拍免费| 亚洲午夜精品网| www久久久久| 欧洲一区在线电影| aaa亚洲精品一二三区| 久久精品国产77777蜜臀| 亚洲一区二区3| 亚洲猫色日本管| 在线不卡中文字幕| 欧日韩精品视频| 大桥未久av一区二区三区中文| 午夜欧美一区二区三区在线播放| 国产精品伦理一区二区| 欧美精品一区二区三区四区| 91久久精品一区二区三区| 国产精品女同一区二区三区| 亚洲视频狠狠干| 欧美偷拍一区二区| a亚洲天堂av| 大白屁股一区二区视频| 日韩高清一区二区| 蜜乳av一区二区三区| 成人欧美一区二区三区| 精品国产麻豆免费人成网站| 欧美伊人久久久久久久久影院 | 91色视频在线| 国产福利一区二区| 日本中文一区二区三区| 亚洲视频综合在线| 欧美成人a∨高清免费观看| 日韩一区二区中文字幕| 欧美高清dvd| 亚洲人成网站色在线观看| 国产亚洲欧美色| 日本午夜精品视频在线观看| 午夜精品福利一区二区蜜股av| 亚洲一区二区在线免费观看视频| 亚洲在线视频免费观看| 亚洲国产色一区| 久久www免费人成看片高清| 韩国精品在线观看|