【代码】golang 实现的文件服务(包括上传,下载的server端和client端)

(2013-09-20 02:03:52)

标签:

golang

go

文件服务器

it

分类: GO相关

//下载(支持断电续传)(client)

package main

import (

   "http"
    "os"
    "io"
   
"strconv"
)

const (
    UA = "Golang
Downloader from Kejibo.com"
)

func main() {
    f, err :=
os.OpenFile("./file.exe", os.O_RDWR, 0666) 
//其实这里的 O_RDWR应该是
O_RDWR|O_CREATE,也就是文件不存在的情况下就建一个空文件,但是因为windows下还有BUG,如果使用这个O_CREATE,就会直接清空文件,所以这里就不用了这个标志,你自己事先建立好文件。

if err !=
nil { panic(err) }
    stat, err :=
f.Stat()  
 //获取文件状态
    if err !=
nil { panic(err) }
   
f.Seek(stat.Size, 0)  
 //把文件指针指到文件末,当然你说为何不直接用 O_APPEND
模式打开,没错是可以。我这里只是试验。
    url :=
"http://dl.google.com/chrome/install/696.57/chrome_installer.exe"

var req
http.Request
    req.Method =
"GET"
   
req.UserAgent = UA
    req.Close =
true
    req.URL, err
= http.ParseURL(url)
    if err !=
nil { panic(err) }
    header :=
http.Header{}
   
header.Set("Range", "bytes=" + strconv.Itoa64(stat.Size) +
"-")
    req.Header =
header
    resp, err :=
http.DefaultClient.Do(&req)
    if err !=
nil { panic(err) }
    written, err
:= io.Copy(f, resp.Body)
    if err !=
nil { panic(err) }
   
println("written: ", written)
}

//下载(server)
package main

import (
    "flag"
    "fmt"
    "io"
    "log"
  
 "net/http"
    "os"
    "path"
  
 "strconv"
)

var dir string
var port int
var staticHandler http.Handler

// 初始化参数
func init() {
    dir =
path.Dir(os.Args[0])
  
 flag.IntVar(&port, "port", 800,
"服务器端口")
  
 flag.Parse()
  
 fmt.Println("dir:", http.Dir(dir))
  
 staticHandler =
http.FileServer(http.Dir(dir))
}

func main() {
  
 http.HandleFunc("/", StaticServer)
    err :=
http.ListenAndServe(":"+strconv.Itoa(port), nil)
    if err !=
nil {
  
   
 log.Fatal("ListenAndServe: ", err)
    }
}

// 静态文件处理
func StaticServer(w http.ResponseWriter, req *http.Request) {
  
 fmt.Println("path:" + req.URL.Path)
    if
req.URL.Path != "/down/" {
  
   
 staticHandler.ServeHTTP(w, req)
  
   
 return
    }

io.WriteString(w, "hello, world!\n")
}

//上传(client)

package main

import (
  
 "bytes"
    "fmt"
    "io"
  
 "io/ioutil"
  
 "mime/multipart"
  
 "net/http"
    "os"
)

func postFile(filename string, targetUrl string) error {
    bodyBuf :=
&bytes.Buffer{}
    bodyWriter
:= multipart.NewWriter(bodyBuf)
  
 //关键的一步操作
    fileWriter,
err := bodyWriter.CreateFormFile("uploadfile", filename)
    if err !=
nil {
  
   
 fmt.Println("error writing to buffer")
  
   
 return err
    }
  
 //打开文件句柄操作
    fh, err :=
os.Open(filename)
    if err !=
nil {
  
   
 fmt.Println("error opening file")
  
   
 return err
    }

//iocopy
    _, err =
io.Copy(fileWriter, fh)
    if err !=
nil {
  
   
 return err
    }
    contentType
:= bodyWriter.FormDataContentType()
  
 bodyWriter.Close()
    resp, err :=
http.Post(targetUrl, contentType, bodyBuf)
    if err !=
nil {
  
   
 return err
    }
    defer
resp.Body.Close()
    resp_body,
err := ioutil.ReadAll(resp.Body)
    if err !=
nil {
  
   
 return err
    }
  
 fmt.Println(resp.Status)
  
 fmt.Println(string(resp_body))

return
nil
}

// sample usage
func main() {
    target_url
:= "http://localhost:9090/upload"
    filename :=
"./astaxie.pdf"
  
 postFile(filename, target_url)
}

//上传(server)
package main

import (
  
 "crypto/md5"
    "flag"
    "fmt"
  
 "html/template"
    "io"
    "log"
  
 "net/http"
    "os"
    "path"
  
 "strconv"
    "time"
)

var dir string
var port int

// 初始化参数
func init() {
    dir =
path.Dir(os.Args[0])
  
 flag.IntVar(&port, "port", 800,
"服务器端口")
  
 flag.Parse()
  
 fmt.Println("dir:", http.Dir(dir))
}

func main() {
  
 http.HandleFunc("/upload", upload)
    err :=
http.ListenAndServe(":"+strconv.Itoa(port), nil)
    if err !=
nil {
  
   
 log.Fatal("ListenAndServe: ", err)
    }
}

// 处理/upload 逻辑
func upload(w http.ResponseWriter, r *http.Request) {
  
 fmt.Println("method:", r.Method) //获取请求的方法
    if r.Method
== "GET" {
  
   
 crutime := time.Now().Unix()
  
   
 h := md5.New()
  
   
 io.WriteString(h, strconv.FormatInt(crutime,
10))
  
   
 token := fmt.Sprintf("%x", h.Sum(nil))
  
   
 t, _ := template.ParseFiles("upload.gtpl")
  
   
 t.Execute(w, token)
    } else
{
  
   
 r.ParseMultipartForm(32 << 20)
  
   
 file, handler, err :=
r.FormFile("uploadfile")
  
   
 if err != nil {
  
   
   
 fmt.Println(err)
  
   
   
 return
  
   
 }
  
   
 defer file.Close()
  
   
 fmt.Fprintf(w, "%v", handler.Header)
  
   
 f, err :=
os.OpenFile("./upload/"+handler.Filename, os.O_WRONLY|os.O_CREATE,
0666)
  
   
 if err != nil {
  
   
   
 fmt.Println(err)
  
   
   
 return
  
   
 }
  
   
 defer f.Close()
  
   
 io.Copy(f, file)
    }
}

golang文件上传和下载的更多相关文章

  1. java web学习总结(二十四) -------------------Servlet文件上传和下载的实现

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  2. (转载)JavaWeb学习总结(五十)——文件上传和下载

    源地址:http://www.cnblogs.com/xdp-gacl/p/4200090.html 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传 ...

  3. JavaWeb学习总结,文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  4. java文件上传和下载

    简介 文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到 ...

  5. 使用jsp/servlet简单实现文件上传与下载

    使用JSP/Servlet简单实现文件上传与下载    通过学习黑马jsp教学视频,我学会了使用jsp与servlet简单地实现web的文件的上传与下载,首先感谢黑马.好了,下面来简单了解如何通过使用 ...

  6. JavaWeb学习总结(五十)——文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  7. 文件上传和下载(可批量上传)——Spring(三)

    在文件上传和下载(可批量上传)——Spring(二)的基础上,发现了文件下载时,只有在Chrome浏览器下文件名正常显示,还有发布到服务器后,不能上传到指定的文件夹目录,如上传20160310.txt ...

  8. 文件上传和下载(可批量上传)——Spring(二)

    针对SpringMVC的文件上传和下载.下载用之前“文件上传和下载——基础(一)”的依然可以,但是上传功能要修改,这是因为springMVC 都为我们封装好成自己的文件对象了,转换的过程就在我们所配置 ...

  9. Struts2 之 实现文件上传和下载

    Struts2  之 实现文件上传和下载 必须要引入的jar commons-fileupload-1.3.1.jar commons-io-2.2.jar 01.文件上传需要分别在struts.xm ...

随机推荐

  1. 新注册域名greenopen.site,向专业道路进军

    新注册域名greenopen.site,向专业道路进军,欢迎访问!届时可以通过 greenopen.site jsxyhelu.github.io 或者jsxyhelu.cnblogs.com 访问本 ...

  2. C++的try_catch异常

    http://blog.sina.com.cn/s/blog_a9303fd901018ost.html 大部分内容转自:http://blog.csdn.net/codestinity/articl ...

  3. JAVA基础知识之IO——对象序列化

    对象序列化 Java对象序列化(Serialize)是指将Java对象写入IO流,反序列化(Deserilize)则是从IO流中恢复该Java对象. 对象序列化将程序运行时内存中的对象以字节码的方式保 ...

  4. ThreadLocal实现线程范围内共享

    线程范围内共享,即是对相同一段代码,在不同的模块调用时使用一份数据,而在另外一个线程中又使用另外一份数据. ThreadLocal使用set方法为一个新的线程增加一条记录,key是各自的线程,valu ...

  5. 一、Java语言基础

    1.标识符和关键字 标识符是java中必须使用的,具有一定的规则,用来标识类名.变量名.方法名.数组名.文件名等. 例:int i = 100;                    变量i就是标识符 ...

  6. 【leetcode❤python】101. Symmetric Tree

    #-*- coding: UTF-8 -*-# Definition for a binary tree node.# class TreeNode(object):#     def __init_ ...

  7. BZOJ 2658 小蓝的好友

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2658 题意:给出一个n*m的格子.某些格子中有障碍.求包含至少一个障碍的矩形有多少 ...

  8. linux下vim命令详解

    高级一些的编辑器,都会包含宏功能,vim当然不能缺少了,在vim中使用宏是非常方便的::qx     开始记录宏,并将结果存入寄存器xq     退出记录模式@x     播放记录在x寄存器中的宏命令 ...

  9. @RequestMapping测试各种访问方式

    这里访问WEB-INF目录下的页面,这个还不知道有没有类似struts2那样的通配符来可以访问不同的action,不同的method,不同 的页面,用户则很爽,有的话求告知,而且我还有一个问题就是配置 ...

  10. hihoCoder太阁最新面经算法竞赛17

    比赛链接:http://hihocoder.com/contest/hihointerview26 A.排序后枚举两个点,确定一个矩形后二分剩下两个点. #include <bits/stdc+ ...