普通接口
web服务器
import (
"io"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", hello)
http.ListenAndServe(":8000", mux)
}
静态文件服务器
import (
"net/http"
"log"
)
func main() {
s := "/Users/admin/go/src/demo";
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(s))))
err := http.ListenAndServe(":8088", nil)
if err != nil {
log.Fatalln("err===", err);
}
}
文件接口
文件上传接口
一般情况下的服务器接收文件代码
// 处理/upload 逻辑
func upload( w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(2024)//缓存为1k
file, handler, err := r.FormFile("uploadfile")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
fmt.Println("文件大小===", handler.Size)
fmt.Println("文件名===", handler.Filename)
//打开一个文件,如果没有就创建
f,err := os.Create("文件名")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
f.Chmod(777)//设置文件权限
buf := make([]byte,1024)//创建一个初始容量为1024的slice,作为缓冲容器
for{
//循环读取文件数据到缓冲容器中,返回读取到的个数
n,err:= file.Read(buf)
if err != nil {
fmt.Println(err)
return
}
if 0==n{
break //如果读到个数为0,则读取完毕,跳出循环
}
//从缓冲slice中写出数据,从slice下标0到n,通过os.Stdout写出到控制台
f.Write(buf[:n])
}
}
base64接收接口
const file_root = "/Users/admin/go/src/lu-activity/file/"
type upload struct {
Base_64 string `json:"base_64"` //
}
// 文件上传接口
func uploadHandler(w http.ResponseWriter, r *http.Request) {
success, encodeByte, file_suf := uploadHandlerParmCheck(w, r)
if !success {
return
}
url, err := saveImgeToFile(file_suf, encodeByte)
if err != nil {
return
}
info := make(map[string]string)
info["url"] = "/v1/file" + url
fmt.Fprintf(w,"%+v" ,info)
return
}
// 参数校验
func uploadHandlerParmCheck(w http.ResponseWriter, r *http.Request) (bool, []byte, string) {
Body := r.Body
body := make([]byte, 0)
buffer := make([]byte, 2048)
for {
n, err := Body.Read(buffer)
if err == io.EOF {
body = append(body, buffer[0:n]...)
break
}
body = append(body, buffer[0:n]...)
}
defer Body.Close()
info := upload{}
err := json.Unmarshal(body, &info)
if err != nil || info.Base_64 == "" {
return false, nil, ""
}
data := strings.Split(info.Base_64, ";base64,")
if !(len(data) >= 2) {
return false, nil, ""
}
encodeByte, err := base64.StdEncoding.DecodeString(data[1]) //成图片文件并把文件写入到buffer
if err != nil {
return false, nil, ""
}
data_type := data[0]
file_suf := ""
switch data_type {
case "data:image/png": //image/jpeg 显示文件内容 试图显示图片2 试图显示图片 试图显示图片 试图显示图片
file_suf = "png"
case "data:image/jpeg":
file_suf = "jpg"
}
return true, encodeByte, file_suf
}
// 保存文件到磁盘
// file_url 图片要保存的文件夹
// file_name 图片要保存的图片名称
// file_suf 图片的后缀名
// data 图片数据
func saveImgeToFile(file_suf string, data []byte) (string, error) {
timenow := time.Now()
pak_name := timenow.Format("2006-01-02 15:04:05")[0:7]
file_name := strconv.FormatInt(timenow.Unix(), 10)
if exist, _ := pathExists(file_root + pak_name); !exist {
err := os.Mkdir(file_root+pak_name, 0777)
if err != nil {
return "", err
}
}
return "/" + file_suf + "/" + file_name, ioutil.WriteFile(file_root+pak_name+"/"+file_name+"."+file_suf, data, 0664) //buffer输出到jpg文件中(不做处理,直接写到文件)
}
/*
* 判断文件是否存在
* 如果返回的错误为nil,说明文件或文件夹存在
* 如果返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在
* 如果返回的错误为其它类型,则不确定是否在存在
*
*/
func pathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
图片文件查看接口
// 查看文件的路径
func fileHandler(w http.ResponseWriter, r *http.Request) {
success, file_path, content_type := fileHandlerParmCheck(w, r)
if !success {
return
}
w.Header().Set("Content-Type", content_type+"; charset=UTF-8")
// 下载文件接口需要加的文件名
// w.Header().Set("Content-Type", "application/octet-stream")
// w.Header().Set("content-disposition", "attachment; filename=\""+"aa.xlsx"+"\"")
http.ServeFile(w, r, file_path)
}
// 文件接口的参数校验
func fileHandlerParmCheck(w http.ResponseWriter, r *http.Request) (bool, string, string) {
// 从路由中获取图片的信息
image_type := mux.RouteVars(r)["type"] // 图片的类型
content_type := ""
switch image_type {
case "png": //image/jpeg 显示文件内容 试图显示图片2 试图显示图片 试图显示图片 试图显示图片
content_type = "image/png"
case "jpg":
content_type = "image/jpeg"
}
if content_type == "" {
return false, "", content_type
}
// 从路由中获取图片的信息
image_id := mux.RouteVars(r)["id"] // 图片的路径及ID
image_nuix, err := strconv.ParseInt(image_id, 10, 64)
if image_id == "" || err != nil {
return false, "", content_type
}
image_time := time.Unix(image_nuix, 0)
return true, file_root + image_time.Format("2006-01-02 15:04:05")[0:7] + "/" + image_id + "." + image_type, content_type
}
const file_root = "/Users/admin/go/src/lu-activity/file/"
文件客户端
上传文件
// filename 上传的文件名称
// reader 文件的读取流
func postFile("文件名",post_url string, reader io.Reader) (PostImageResult, error) {
result := PostImageResult{}
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
//关键的一步操作
fileWriter, err := bodyWriter.CreateFormFile("取文件的key值", filename)
if err != nil {
fmt.Println("error writing to buffer")
return result, err
}
_, err = io.Copy(fileWriter, reader)
if err != nil {
return result, err
}
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
resp, err := http.Post(post_url, contentType, bodyBuf)
if err != nil {
return result, err
}
defer resp.Body.Close()
resp_body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return result, err
}
err = json.Unmarshal(resp_body, &result)
if err != nil {
return result, err
}
return result, nil
}
下载文件
func main() {
f, err := os.Create("./file.exe") //其实这里的 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"
resp, err := http.Get(url)
if err != nil { panic(err) }
written, err := io.Copy(f, resp.Body)
if err != nil { panic(err) }
println("written: ", written)
}