package main import ( "html/template" "io" "io/ioutil" "log" "net/http" "os" "path" "runtime/debug" ) const ( ListDir = 0x0001 UPLOAD_DIR = "./uploads" TEMPLATE_DIR = "./views" ) //cache storage all template var templates = make(map[string]*template.Template) func init() { fileInfoArr, err := ioutil.ReadDir(TEMPLATE_DIR) check(err) var templateName, templatePath string for _, fileInfo := range fileInfoArr { templateName = fileInfo.Name() if ext := path.Ext(templateName); ext != ".html" { continue } templatePath = TEMPLATE_DIR + "/" + templateName //log.Println(templateName) log.Println("Loading template:", templatePath) t := template.Must(template.ParseFiles(templatePath)) templates[templateName] = t } //if const template /*for _, tmpl := range []string{"upload", "list"} { //Must ensure in case can't analytic will do error operate,If the template loading is not successful, the program will exit t := template.Must(template.ParseFiles(tmpl + ".html")) templates[tmpl] = t }*/ } func check(err error) { if err != nil { panic(err) } } func renderHtml(w http.ResponseWriter, tmpl string, locals map[string]interface{}) { /*tt := templates[tmpl] log.Println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", templates, tmpl, tt)*/ log.Println(locals) err := templates[tmpl].Execute(w, locals) check(err) } func isExists(path string) bool { _, err := os.Stat(path) //log.Println(err) if err == nil { return true } return os.IsExist(err) } //Callback method, func uploadHandler(w http.ResponseWriter, r *http.Request) { //log.Println(r.Method) if r.Method == "GET" { renderHtml(w, "upload.html", nil) } if r.Method == "POST" { f, h, err := r.FormFile("image") //log.Println(f, h, err) check(err) filename := h.Filename defer f.Close() //log.Println(UPLOAD_DIR, filename) t, err := ioutil.TempFile(UPLOAD_DIR, filename) //log.Println(t) check(err) defer t.Close() _, err = io.Copy(t, f) //dst src check(err) http.Redirect(w, r, "/view?
id="+filename, http.StatusFound)
} } func viewHandler(w http.ResponseWriter, r *http.Request) { imageId := r.FormValue("id")imagePath := UPLOAD_DIR + "/" + imageIdlog.Println(imageId, imagePath)if exists := isExists(imagePath); !exists { http.NotFound(w, r)return}//log.Println("222222222222")w.Header().Set("Content-Type", "image")http.ServeFile(w, r, imagePath) } func listHandler(w http.ResponseWriter, r *http.Request) { fileInfoArr, err := ioutil.ReadDir("./uploads")//log.Println(fileInfoArr)check(err)if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError)return}locals := make(map[string]interface{})images := []string{}for _, fileInfo := range fileInfoArr { //log.Println(fileInfo)images = append(images, fileInfo.Name())}locals["images"] = images //这里map的key是images,相应list.html里面的$.imagesrenderHtml(w, "list.html", locals) } //巧用闭包避免执行时错误崩溃 func safeHandler(fn http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { defer func() { log.Println("can't past execute or finished execute")if e, ok := recover().(error); ok { log.Println("50x error")//50x errorhttp.Error(w, e.Error(), http.StatusInternalServerError)log.Println("Warn : panic in %v. - %v", fn, e)log.Println(string(debug.Stack()))}}()log.Println("if no panic then first execute")fn(w, r)} } func staticDirHandler(mux *http.ServeMux, prefix string, staticDir string, flags int) { mux.HandleFunc(prefix, func(w http.ResponseWriter, r *http.Request) { file := staticDir + r.URL.Path[len(prefix)-1:]if (flags & ListDir) == 0 { if exists := isExists(file); !exists { http.NotFound(w, r)return}}http.ServeFile(w, r, file)}) } func main() { mux := http.NewServeMux()staticDirHandler(mux, "/assets/", "./public", 0)mux.HandleFunc("/", safeHandler(listHandler))mux.HandleFunc("/view", safeHandler(viewHandler))mux.HandleFunc("/upload", safeHandler(uploadHandler))err := http.ListenAndServe(":8080", mux)if err != nil { log.Fatal("ListenAndServe:", err.Error())}}
uoload.html
<html>
<head><meta charset="utf-8"><title>upload</title></head><body><form method="POST" action="/upload" enctype="multipart/form-data">choosing an image to upload :<br><input name="image" type="file"><input type="submit" value="Upload"></form></body> </html>list.html
<html>
<head><meta charset="utf-8"><title>list</title></head><body><ol>{ {range $.images}}<li><a href="/view?id={ {.|urlquery}}">{ {.|html}}</a></li>{ {end}}</ol></body> </html>注意文件结构
photoweb
-photoweb.go
-public
-js
-css
-images
-uploads
-views
-upload.html
-list.html
解决调用七牛音频问题
演示样例仅仅提供代码方式调用api,不可以像图片处理直接在url中加入參数进行改动
若强用url会提示要预处理音频转码。一般转码採用异步方式
OK,在go的SDK代码中进行,结果发现api给的參数仅仅是个大概,go的api里面的相应參数。不全然和官网贴出来的一样
我们搜需PutPolicy
在rs/token.go 中,看到相应deadline。grep 'xx' * -R查看文件中内容
package main
import ("fmt". "github.com/qiniu/api/conf""github.com/qiniu/api/fop""github.com/qiniu/api/io""github.com/qiniu/api/rs""log" ) func init() { ACCESS_KEY = "自己的ak"SECRET_KEY = "自己sk" } //GET upload access token func uptoken(bucketName string) string { putPolicy := rs.PutPolicy{ Scope: bucketName,//CallbackUrl: callbackUrl,//CallbackBody:callbackBody,//ReturnUrl: returnUrl,//ReturnBody: returnBody,//AsyncOps: asyncOps,//EndUser: endUser,//Expires: expires,Expires: 1406555272, //截止时间戳PersistentOps: "avthumb/mp3",PersistentNotifyUrl: "http://fake.com/qiniu/notify",}return putPolicy.Token(nil) } func main() { //上传本地文件upload("a")//5.1 获取文件信息//getFileInfo()//6.1.1 查看图像属性//imageAttr()//5.2 删除文件//delFile() } //6.1.1 查看图像属性 func imageAttr() { var imageUrl = "http://needkane.qiniudn.com/kane2.jpg"ii := fop.ImageInfo{}infoRet, err := ii.Call(nil, imageUrl)if err != nil { // 产生错误log.Println("fop getImageInfo failed:", err)return}log.Println(infoRet.Height, infoRet.Width, infoRet.ColorModel, infoRet.Format) } func makeImageInfoUrl(imageUrl string) string { ii := fop.ImageInfo{}return ii.MakeRequest(imageUrl) } //5.2 删除文件 func delFile() { bucket := "needkane"key := "goupload.jpg"var rsCli = rs.New(nil)err := rsCli.Delete(nil, bucket, key)if err != nil { // 产生错误log.Println("rs.Copy failed:", err)return} } //5.1 获取文件信息 func getFileInfo() { var ret rs.Entrybucket := "needkane"key := "kane3.jpg"var rsCli = rs.New(nil)var err errorret, err = rsCli.Stat(nil, bucket, key)if err != nil { // 产生错误log.Println("rs.Stat failed:", err)return}// 处理返回值log.Println(ret) } //上传本地文件 func upload(key string) { uptoken := uptoken("needkane")fmt.Printf("uptoken:%s\n", uptoken)var err errorvar ret io.PutRetvar extra = &io.PutExtra{ //Params: params,//MimeType: mieType,//Crc32: crc32,//CheckCrc: CheckCrc,}var localFile = "/home/qboxtest/Downloads/a.wav"// ret 变量用于存取返回的信息,详情见 io.PutRet// uptoken 为业务server生成的上传口令// key 为文件存储的标识// localFile 为本地文件名称// extra 为上传文件的额外信息。详情见 io.PutExtra,可选err = io.PutFile(nil, &ret, uptoken, key, localFile, extra)if err != nil { //上传产生错误log.Print("io.PutFile failed:", err)return}//上传成功,处理返回值log.Print(ret.Hash, ret.Key) }用 file 命令查看文件