├── .gitignore ├── README ├── build.bat ├── go.mod └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | tmp_file/ 2 | *.exe 3 | 4 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 局域网下电脑手机文件互传(linux也行吧,但是因为WSL网卡问题没测,需要改路径拼接) 2 | 3 | 编译后再运行 4 | file_kiri.exe -ip={路由器下电脑的ip} 5 | 比如: 6 | file_kiri.exe -ip=192.168.50.223 7 | 8 | 9 | 使用方法: 10 | 11 | 手机to电脑: 12 | 1.手机打开 http://你的ip:8080/upload 选择文件然后点击upload即可,文件会下载到程序运行目录下的"tmp_file" 13 | 14 | 15 | 电脑to手机: 16 | 1.首先要传输的文件copy到程序运行目录下的"tmp_file" 17 | 2.手机打开 http://你的ip:8080/files/{文件名} 替换文件名即可 18 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | go build -o file_kiri.exe 2 | @REM COPY file_kiri.exe D:\aliez\ 3 | @REM CD D:\aliez\ 4 | @REM file_kiri.exe -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module ts 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "net" 9 | "net/http" 10 | "os" 11 | "path/filepath" 12 | "runtime" 13 | ) 14 | 15 | const ( 16 | MaxUploadSize = 10 << 30 // 10GB 17 | ) 18 | 19 | var ( 20 | uploadPath = "" 21 | ip_port = "" 22 | ip = flag.String("ip", "", "电脑路由器ip地址") 23 | port = flag.Int("port", 8080, "程序运行端口,默认8080") 24 | ) 25 | 26 | func init() { 27 | showIPs() 28 | 29 | flag.Parse() 30 | if *ip == "" { 31 | panic("ip需要指定,即电脑路由器ip地址.比如:file_kiri.exe -ip=192.168.50.223 -port=8080") 32 | } 33 | ip_port = fmt.Sprintf("%s:%d", *ip, *port) 34 | 35 | exe_path, err := os.Executable() 36 | if err != nil { 37 | panic(err) 38 | } 39 | 40 | current_path := filepath.Dir(exe_path) 41 | uploadPath = fmt.Sprintf("%s\\%s", current_path, "tmp_file") 42 | fmt.Printf("执行程序的路径: [%s]文件暂存路径: [%s]\n", current_path, uploadPath) 43 | 44 | err = os.Mkdir(uploadPath, os.ModeDir) 45 | if err != nil && !os.IsExist(err) { 46 | panic(err) 47 | } 48 | } 49 | 50 | func main() { 51 | http.HandleFunc("/upload", uploadFileHandler()) 52 | fs := http.FileServer(http.Dir(uploadPath)) 53 | http.Handle("/files/", http.StripPrefix("/files", fs)) 54 | 55 | upload_url := fmt.Sprintf("http://%s/upload", ip_port) 56 | download_url := fmt.Sprintf("http://%s/files/{文件名}", ip_port) 57 | 58 | fmt.Printf("NOTICE: %s for upload \n%s for download\n", upload_url, download_url) 59 | log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)) 60 | } 61 | 62 | func uploadFileHandler() http.HandlerFunc { 63 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 64 | s := ` 65 | 66 | 局域网文件交换 67 | 68 | 69 |
70 | 71 | 72 |
73 | 74 | ` 75 | html := fmt.Sprintf(s, ip_port) 76 | 77 | if r.Method == http.MethodGet { 78 | fmt.Fprint(w, html) 79 | return 80 | } 81 | 82 | if r.Method == http.MethodPost { 83 | file, fileHeader, err := r.FormFile("uploadFile") 84 | if err != nil { 85 | renderError(w, "文件读取出错", http.StatusBadRequest) 86 | return 87 | } 88 | defer file.Close() 89 | 90 | fileSize := fileHeader.Size 91 | fmt.Printf("文件大小: %.2fMB\n", float64(fileSize)/1024/1024) 92 | 93 | if fileSize > MaxUploadSize { 94 | renderError(w, "文件过大", http.StatusBadRequest) 95 | return 96 | } 97 | 98 | fileBytes, err := ioutil.ReadAll(file) 99 | if err != nil { 100 | renderError(w, "文件读取出错", http.StatusBadRequest) 101 | return 102 | } 103 | 104 | detectedFileType := http.DetectContentType(fileBytes) 105 | 106 | // fileEndings, err := mime.ExtensionsByType(detectedFileType) 107 | // if err != nil { 108 | // renderError(w, fmt.Sprintf("无法写入的类型%s\n", err), http.StatusInternalServerError) 109 | // return 110 | // } 111 | // fmt.Printf("文件类型:[%s]\n", fileEndings[0]) 112 | 113 | // newPath := filepath.Join(uploadPath, fileHeader.Filename+fileEndings[0]) 114 | newPath := filepath.Join(uploadPath, fileHeader.Filename) 115 | fmt.Printf("文件类型: [%s], 存储路径: [%s]\n", detectedFileType, newPath) 116 | 117 | newFile, err := os.Create(newPath) 118 | if err != nil { 119 | renderError(w, fmt.Sprintf("写入失败1%s\n", err), http.StatusInternalServerError) 120 | return 121 | } 122 | defer newFile.Close() 123 | 124 | if _, err := newFile.Write(fileBytes); err != nil || newFile.Close() != nil { 125 | renderError(w, fmt.Sprintf("写入失败2%s\n", err), http.StatusInternalServerError) 126 | return 127 | } 128 | 129 | runtime.GC() 130 | w.Write([]byte("OK")) 131 | } 132 | }) 133 | } 134 | 135 | func showIPs() { 136 | fmt.Println("下面其中一个是路由器地址,选取一个作为启动参数:") 137 | fmt.Println("*****************************") 138 | defer fmt.Println("*****************************") 139 | 140 | addrs, err := net.InterfaceAddrs() 141 | if err != nil { 142 | panic(err) 143 | } 144 | 145 | for _, address := range addrs { 146 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 147 | if ipnet.IP.To4() != nil { 148 | fmt.Println("\t", ipnet.IP.String()) 149 | } 150 | } 151 | } 152 | } 153 | 154 | func renderError(w http.ResponseWriter, message string, statusCode int) { 155 | // statusCode 156 | w.WriteHeader(http.StatusBadRequest) 157 | w.Write([]byte(message)) 158 | } 159 | --------------------------------------------------------------------------------