【问题标题】:Zip a Directory and not Have the Result Saved in File System压缩目录并且没有将结果保存在文件系统中
【发布时间】:2021-07-12 06:39:35
【问题描述】:

我能够使用类似于here 中看到的 zip 编写器的逻辑来压缩文件。

这会导致在返回的bytes.Buffer 对象中创建一个字节数组 ([]byte)。我想知道是否有任何方法可以将这个“压缩”字节数组上传到一个 API 端点,该端点需要一个“multipart/form-data”请求正文(无需在本地保存)。

补充资料:

我的代码在压缩文件夹时使用了this。我能够使用此逻辑成功地执行带有 zip 文件的 HTTP POST 请求到端点。

但是,不幸的是,这会将压缩文件保存在用户的本地文件系统中。我想尽量避免这种情况:)

【问题讨论】:

  • 您的问题是 zip 文件留在文件系统中吗?如果是这样,您可以在上传完成后随时将其删除。或者您可以在操作系统的临时目录中创建 zip 文件并将其留给操作系统自动删除。
  • 我想尽量不要让 zip 文件留在文件系统期间 :) 有点像“zip 流”(我认为这是正确的术语)
  • 在第二个示例代码中,您可以将newZipFile, err := os.Create(filename) 替换为第一个示例中的buf := new(bytes.Buffer),然后使用buf 而不是newZipFile 创建编写器,即zipWriter := zip.NewWriter(buf)。跨度>

标签: go zip filesystems gzip


【解决方案1】:

您可以创建多部分写入器,并将 []byte 压缩数据写入字段,您喜欢的字段名称和文件名如下所示。

func addZipFileToReq(zipped []byte)  (*http.Request, error){
    body := bytes.NewBuffer(nil)
    writer := multipart.NewWriter(body)
    part, err := writer.CreateFormFile(`fileField`, `filename`)
    if err != nil {
        return nil, err
    }
    _, err = part.Write(zipped)
    if err != nil {
        return nil, err
    }
    err = writer.Close()
    if err != nil {
        return nil, err
    }

    r, err := http.NewRequest(http.MethodPost, "https://example.com", body)
    if err != nil {
        return nil, err
    }
    r.Header.Set("Content-Type", writer.FormDataContentType())

    return r, nil
}

【讨论】:

    【解决方案2】:

    如果您想流式上传 zip,您应该可以使用 io.Pipe 进行此操作。以下是一个不完整且未经测试的示例,用于演示总体思路。要使其正常工作,您需要对其进行修改并可能修复您遇到的任何错误。

    func UploadReader(r io.Reader) error {
        req, err := http.NewRequest("POST", "<UPLOAD_URL>", r)
        if err != nil {
            return err
        }
    
        // TODO set necessary headers (content type, auth, etc)
    
        res, err := http.DefaultClient.Do(req)
        if err != nil {
            return err
        } else if res.StatusCode != 200 {
            return errors.New("not ok")
        }
        return nil
    }
    
    func ZipDir(dir string, w io.Writer) error {
        zw := zip.NewWriter(w)
        defer zw.Close()
    
        return filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
            if err != nil {
                return err
            }
            if !fi.Mode().IsRegular() {
                return nil
            }
    
            header, err := zip.FileInfoHeader(fi)
            if err != nil {
                return err
            }
            header.Name = path
            header.Method = zip.Deflate
    
            w, err := zw.CreateHeader(header)
            if err != nil {
                return err
            }
    
            f, err := os.Open(path)
            if err != nil {
                return err
            }
            defer f.Close()
    
            if _, err := io.Copy(w, f); err != nil {
                return err
            }
            return nil
        })
    }
    
    func UploadDir(dir string) error {
        r, w := io.Pipe()
    
        ch := make(chan error)
        wg := sync.WaitGroup{}
    
        wg.Add(1)
        go func() {
            defer wg.Done()
            defer w.Close()
    
            if err := ZipDir(dir, w); err != nil {
                ch <- err
            }
        }()
    
        wg.Add(1)
        go func() {
            defer wg.Done()
            defer r.Close()
    
            if err := UploadReader(r); err != nil {
                ch <- err
            }
        }()
    
        go func() {
            wg.Wait()
            close(ch)
        }()
    
        return <-ch
    }
    

    【讨论】:

      猜你喜欢
      • 2015-07-19
      • 1970-01-01
      • 2012-05-29
      • 2016-02-05
      • 1970-01-01
      • 2014-10-25
      • 2013-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多