压缩目录,而不将结果保存在文件系统中



我可以使用类似于这里的zip编写器的逻辑来压缩文件。

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

补充信息:

我有一些代码在压缩文件夹时利用了这一点。使用此逻辑,我能够成功地使用zip文件执行HTTPPOST请求到端点。

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

您可以创建多部分写入程序,并将[]字节压缩后的数据写入您喜欢的字段名和如下文件名的字段中。

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
}

如果您想流式上传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
}

最新更新