You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
7.1 KiB
Go
262 lines
7.1 KiB
Go
package tools
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"b612.me/starainrt"
|
|
|
|
"b612.me/starlog"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var port, ip, path string
|
|
var up bool
|
|
|
|
type TraceHandler struct {
|
|
h http.Handler
|
|
}
|
|
|
|
// httpCmd represents the http command
|
|
var httpcmd = &cobra.Command{
|
|
Use: "http",
|
|
Short: "HTTP文件服务器",
|
|
Long: `HTTP文件服务器`,
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
http.HandleFunc("/", httplisten)
|
|
path, _ = filepath.Abs(path)
|
|
fmt.Println("Listening On Port:" + port)
|
|
if up {
|
|
fmt.Println("upload is openned,path is /vtqeupload1127")
|
|
http.HandleFunc("/vtqeupload1127", uploadfile)
|
|
}
|
|
err := http.ListenAndServe(ip+":"+port, nil)
|
|
if err != nil {
|
|
starlog.StdPrintln(0, starlog.RED, "Error:"+err.Error())
|
|
}
|
|
},
|
|
}
|
|
|
|
func uploadfile(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" {
|
|
w.Write([]byte("USE POST METHOD!"))
|
|
return
|
|
}
|
|
r.ParseMultipartForm(10485760)
|
|
file, handler, err := r.FormFile("victorique")
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
w.WriteHeader(502)
|
|
w.Write([]byte(err.Error()))
|
|
return
|
|
}
|
|
defer file.Close()
|
|
fmt.Printf("Upload %s From %s\n", handler.Filename, r.RemoteAddr)
|
|
fmt.Fprintf(w, `<html><body><p>%v</p><h2><a href="./vtqeupload1127/web">Return To Web Page</a></h2></body></html>`, handler.Header)
|
|
os.Mkdir("./vtqeupload1127", 0755)
|
|
f, err := os.OpenFile("./vtqeupload1127/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0755)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
defer f.Close()
|
|
io.Copy(f, file)
|
|
}
|
|
|
|
func httplisten(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Server", "Vicorique")
|
|
w.Header().Set("Powered", "B612.ME")
|
|
p := r.URL.Path
|
|
cmd := r.URL.Query()["cmd"]
|
|
fmt.Println("Get " + p + " " + r.RemoteAddr)
|
|
fullpath, _ := filepath.Abs(path + p)
|
|
|
|
if p == "/" {
|
|
ReadFolder(w, r, fullpath, true)
|
|
return
|
|
}
|
|
if up {
|
|
if p == "/vtqeupload1127/web" {
|
|
w.Write([]byte(`<html><body><form id= "uploadForm" action= "../vtqeupload1127" method= "post" enctype ="multipart/form-data">
|
|
<h1 >B612 File Upload Page </h1>
|
|
<p >上传文件: <input type ="file" name="victorique" /></p>
|
|
<input type ="submit" value="上传"/>
|
|
</form>
|
|
<h2>Copyright@b612.me </h2></body></html>`))
|
|
return
|
|
}
|
|
}
|
|
if !starainrt.Exists(fullpath) {
|
|
w.WriteHeader(404)
|
|
if len(cmd) != 0 {
|
|
if cmd[0] == "header" {
|
|
for k, v := range r.Header {
|
|
for _, v2 := range v {
|
|
fmt.Fprintf(w, "%s:%s\n", k, v2)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
w.Write([]byte("<h1>404 NOT FOUND</h1>"))
|
|
return
|
|
}
|
|
if starainrt.IsFolder(fullpath) {
|
|
ReadFolder(w, r, fullpath, false)
|
|
return
|
|
}
|
|
fpdst, err := os.Open(fullpath)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
w.WriteHeader(403)
|
|
w.Write([]byte("<h1>403 NO ACCESS</h1>"))
|
|
return
|
|
}
|
|
fpinfo, _ := os.Stat(fullpath)
|
|
name := filepath.Base(fullpath)
|
|
tmp := strings.Split(name, ".")
|
|
ext := ""
|
|
if len(tmp) >= 2 {
|
|
ext = strings.ToLower(tmp[len(tmp)-1])
|
|
}
|
|
switch ext {
|
|
case "jpeg", "jpg", "jpe":
|
|
w.Header().Set("Content-Type", "image/jpeg")
|
|
case "mpeg", "mpg", "mkv":
|
|
w.Header().Set("Content-Type", "video/mpeg")
|
|
case "mp4":
|
|
w.Header().Set("Content-Type", "video/mp4")
|
|
case "pdf":
|
|
w.Header().Set("Content-Type", "application/pdf")
|
|
default:
|
|
w.Header().Set("Content-Type", "application/download")
|
|
w.Header().Set("Content-Disposition", "attachment;filename="+name)
|
|
}
|
|
etag := new(starainrt.StarCrypto).MD5([]byte(fpinfo.ModTime().String()))
|
|
w.Header().Set("Content-Transfer-Encoding", "binary")
|
|
w.Header().Set("Accept-Ranges", "bytes")
|
|
w.Header().Set("ETag", etag)
|
|
w.Header().Set("Last-Modified", fpinfo.ModTime().Format("Mon,2 Jan 2006 15:04:05 MST"))
|
|
isRange := false
|
|
var rangeStart, rangeEnd int64
|
|
rangeEnd = -1
|
|
for k, v := range r.Header {
|
|
if strings.ToLower(k) == "range" {
|
|
if strings.Index(v[0], "bytes=") < 0 {
|
|
break
|
|
}
|
|
v[0] = strings.Replace(v[0], "bytes=", "", -1)
|
|
data := strings.Split(v[0], "-")
|
|
if len(data) == 0 {
|
|
break
|
|
}
|
|
rangeStart, _ = strconv.ParseInt(data[0], 10, 64)
|
|
if len(data) == 2 {
|
|
rangeEnd, _ = strconv.ParseInt(data[1], 10, 64)
|
|
}
|
|
//w.WriteHeader(206) //206 支持断点续传
|
|
isRange = true
|
|
break
|
|
}
|
|
}
|
|
defer fpdst.Close()
|
|
if !isRange {
|
|
w.Header().Set("Content-Length", strconv.FormatInt(fpinfo.Size(), 10))
|
|
w.WriteHeader(200)
|
|
for {
|
|
buf := make([]byte, 1048576)
|
|
n, err := fpdst.Read(buf)
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
return
|
|
}
|
|
w.Write(buf[0:n])
|
|
}
|
|
} else {
|
|
w.Header().Set("Content-Length", strconv.FormatInt(fpinfo.Size(), 10))
|
|
if rangeEnd == -1 {
|
|
w.Header().Set("Content-Range", `bytes `+strconv.FormatInt(rangeStart, 10)+"-"+strconv.FormatInt(fpinfo.Size(), 10)+"/"+strconv.FormatInt(fpinfo.Size(), 10))
|
|
//w.Header().Set("Content-Length", strconv.FormatInt(fpinfo.Size()-rangeStart, 10))
|
|
} else {
|
|
w.Header().Set("Content-Range", `bytes `+strconv.FormatInt(rangeStart, 10)+"-"+strconv.FormatInt(rangeEnd, 10)+"/"+strconv.FormatInt(fpinfo.Size(), 10))
|
|
//w.Header().Set("Content-Length", strconv.FormatInt(1+rangeEnd-rangeStart, 10))
|
|
}
|
|
w.WriteHeader(206)
|
|
fpdst.Seek(int64(rangeStart), 0)
|
|
count := rangeStart
|
|
for {
|
|
buf := make([]byte, 1048576)
|
|
n, err := fpdst.Read(buf)
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
return
|
|
}
|
|
if rangeEnd == -1 {
|
|
w.Write(buf[0:n])
|
|
} else {
|
|
if count > rangeEnd {
|
|
break
|
|
}
|
|
if count+int64(n) > rangeEnd {
|
|
w.Write(buf[0 : rangeEnd-count+1])
|
|
break
|
|
} else {
|
|
w.Write(buf[0:n])
|
|
count += int64(n)
|
|
}
|
|
}
|
|
}
|
|
fmt.Println(fpinfo.Name(), "客户端下载已结束")
|
|
}
|
|
}
|
|
|
|
func ReadFolder(w http.ResponseWriter, r *http.Request, fullpath string, isroot bool) {
|
|
dir, err := ioutil.ReadDir(fullpath)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
w.WriteHeader(403)
|
|
w.Write([]byte("<h1>May Cannot Access!</h1>"))
|
|
}
|
|
w.Write([]byte("<html>\n<style>\np{margin: 2px auto}\n</style>\n<h1>B612 Http Server - " + Version + "</h1>"))
|
|
if up {
|
|
w.Write([]byte("<a href=/vtqeupload1127/web>Upload Web Page Is Openned!</a><br /><br />"))
|
|
}
|
|
w.Write([]byte("<hr /><pre>\n"))
|
|
if r.URL.Path == "/" {
|
|
r.URL.Path = ""
|
|
} else if r.URL.Path[len(r.URL.Path)-1:] == "/" {
|
|
r.URL.Path = r.URL.Path[0 : len(r.URL.Path)-1]
|
|
}
|
|
if !isroot {
|
|
w.Write([]byte(fmt.Sprintf("<p><a href='%s'>%s</a> %s</p>\n", r.URL.Path+"/..", "..", "上层文件夹")))
|
|
}
|
|
for _, v := range dir {
|
|
if v.Name() != "." || v.Name() != ".." {
|
|
if !v.IsDir() {
|
|
w.Write([]byte(fmt.Sprintf("<p><a href='%s'>%s</a> %d %s</p>\n", r.URL.Path+"/"+v.Name(), v.Name(), int(v.Size()), v.ModTime().Format("2006-01-02 15:04:05"))))
|
|
} else {
|
|
w.Write([]byte(fmt.Sprintf("<p><a href='%s'>%s</a> %s %s</p>\n", r.URL.Path+"/"+v.Name(), v.Name(), "文件夹", v.ModTime().Format("2006-01-02 15:04:05"))))
|
|
}
|
|
}
|
|
}
|
|
w.Write([]byte("</pre>\n</html>"))
|
|
return
|
|
}
|
|
func init() {
|
|
httpcmd.Flags().StringVarP(&port, "port", "p", "80", "监听端口")
|
|
httpcmd.Flags().StringVarP(&ip, "ip", "i", "0.0.0.0", "监听ip")
|
|
httpcmd.Flags().StringVarP(&path, "folder", "f", "./", "本地文件地址")
|
|
httpcmd.Flags().BoolVarP(&up, "upload", "u", false, "是否开启文件上传")
|
|
Maincmd.AddCommand(httpcmd)
|
|
}
|