package controller import ( "archive/tar" "archive/zip" "compress/gzip" "encoding/json" "errors" "fmt" "io" "io/ioutil" "net" "os" "path" "pikapi/main/database/comic_center" "pikapi/main/utils" "strings" "time" ) // 通过局域网导出 var exportingListener net.Listener var exportingConn net.Conn func exportComicUsingSocket(comicId string) (int, error) { var err error exportingListener, err = net.Listen("tcp", ":0") if err != nil { return 0, err } go handleExportingConn(comicId) return exportingListener.Addr().(*net.TCPAddr).Port, nil } func handleExportingConn(comicId string) { defer exportingListener.Close() var err error exportingConn, err = exportingListener.Accept() if err != nil { notifyExport(fmt.Sprintf("导出失败")) println(err.Error()) return } defer exportingConn.Close() gw := gzip.NewWriter(exportingConn) defer gw.Close() tw := tar.NewWriter(gw) defer tw.Close() err = exportComicDownloadFetch(comicId, func(path string, size int64) (io.Writer, error) { header := tar.Header{} header.Name = path header.Size = size return tw, tw.WriteHeader(&header) }) if err != nil { notifyExport(fmt.Sprintf("导出失败")) } else { notifyExport(fmt.Sprintf("导出成功")) } } func exportComicUsingSocketExit() error { if exportingConn != nil { exportingConn.Close() } if exportingListener != nil { exportingListener.Close() } return nil } func exportComicDownload(params string) (filePath string, err error) { var paramsStruct struct { ComicId string `json:"comicId"` Dir string `json:"dir"` } json.Unmarshal([]byte(params), ¶msStruct) comicId := paramsStruct.ComicId dir := paramsStruct.Dir println(fmt.Sprintf("导出 %s 到 %s", comicId, dir)) comic, err := comic_center.FindComicDownloadById(comicId) if err != nil { return } if comic == nil { err = errors.New("not found") return } if !comic.DownloadFinished { err = errors.New("not download finish") return } filePath = path.Join(dir, fmt.Sprintf("%s-%s.zip", reasonablePath(comic.Title), time.Now().Format("2006_01_02_15_04_05.999"))) println(fmt.Sprintf("ZIP : %s", filePath)) fileStream, err := os.Create(filePath) if err != nil { return } defer fileStream.Close() zipWriter := zip.NewWriter(fileStream) defer zipWriter.Close() err = exportComicDownloadFetch(comicId, func(path string, size int64) (io.Writer, error) { header := tar.Header{} header.Name = path header.Size = size return zipWriter.Create(path) }) return } func reasonablePath(title string) string { title = strings.ReplaceAll(title, "\\", "_") title = strings.ReplaceAll(title, "/", "_") title = strings.ReplaceAll(title, "*", "_") title = strings.ReplaceAll(title, "?", "_") title = strings.ReplaceAll(title, "<", "_") title = strings.ReplaceAll(title, ">", "_") title = strings.ReplaceAll(title, "|", "_") return title } func exportComicDownloadFetch(comicId string, onWriteFile func(path string, size int64) (io.Writer, error)) error { comic, err := comic_center.FindComicDownloadById(comicId) if err != nil { return err } if comic == nil { return errors.New("not found") } if !comic.DownloadFinished { return errors.New("not download finish") } epList, err := comic_center.ListDownloadEpByComicId(comicId) if err != nil { return err } jsonComic := JsonComicDownload{} jsonComic.ComicDownload = *comic jsonComic.EpList = make([]JsonComicDownloadEp, 0) for _, ep := range epList { jsonEp := JsonComicDownloadEp{} jsonEp.ComicDownloadEp = ep jsonEp.PictureList = make([]JsonComicDownloadPicture, 0) pictures, err := comic_center.ListDownloadPictureByEpId(ep.ID) if err != nil { return err } for _, picture := range pictures { jsonPicture := JsonComicDownloadPicture{} jsonPicture.ComicDownloadPicture = picture jsonPicture.SrcPath = fmt.Sprintf("pictures/%04d_%04d", ep.EpOrder, picture.RankInEp) notifyExport(fmt.Sprintf("正在导出 EP:%d PIC:%d", ep.EpOrder, picture.RankInEp)) entryWriter, err := onWriteFile(jsonPicture.SrcPath, jsonPicture.FileSize) if err != nil { return err } source, err := os.Open(downloadPath(picture.LocalPath)) if err != nil { return err } _, err = func() (int64, error) { defer source.Close() return io.Copy(entryWriter, source) }() if err != nil { return err } jsonEp.PictureList = append(jsonEp.PictureList, jsonPicture) } jsonComic.EpList = append(jsonComic.EpList, jsonEp) } if comic.ThumbLocalPath != "" { logoBuff, err := ioutil.ReadFile(downloadPath(comic.ThumbLocalPath)) if err == nil { entryWriter, err := onWriteFile("logo", int64(len(logoBuff))) if err != nil { return err } _, err = entryWriter.Write(logoBuff) if err != nil { return err } } } // JS { buff, err := json.Marshal(&jsonComic) if err != nil { return err } logoBuff := append([]byte("data = "), buff...) if err == nil { entryWriter, err := onWriteFile("data.js", int64(len(logoBuff))) if err != nil { return err } _, err = entryWriter.Write(logoBuff) if err != nil { return err } } } // HTML { var htmlBuff = []byte(indexHtml) if err == nil { entryWriter, err := onWriteFile("index.html", int64(len(htmlBuff))) if err != nil { return err } _, err = entryWriter.Write(htmlBuff) if err != nil { return err } } } println("OK") // return nil } const indexHtml = `