编辑内存中的zip文件并通过http响应返回它会导致文件损坏 [英] Editing zip file in memory and returning it via http response results in a corrupt file

查看:52
本文介绍了编辑内存中的zip文件并通过http响应返回它会导致文件损坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嘿,新手们刚好走了23小时10分钟,所以显然有些东西出现了问题,我的内存中有一个zip文件,我想拿这个文件做一个副本,添加一些文件到副本并通过HTTP返回文件,它可以工作,但是当我打开文件时,文件似乎已损坏

Hey guys am new to go exactly 23 hours and 10 minutes new so obviously am having issues with some stuff, I have a zip file that is in memory and I would like to take that file make a copy of it add some files to the copy and return the file via HTTP, it works but when I open the file it seems to be corrupted

outFile, err := os.OpenFile("./template.zip", os.O_RDWR, 0666)
if err != nil {
    log.Fatalf("Failed to open zip for writing: %s", err)
}
defer outFile.Close()


zipw := zip.NewWriter(outFile)

fmt.Println(reflect.TypeOf(zipw))
for _, appCode := range appPageCodeText {
    f, err := zipw.Create(appCode.Name + ".jsx")

    if err != nil {
        log.Fatal(err)
    }

    _, err = f.Write([]byte(appCode.Content)) //casting it to byte array and writing to file
}

// Clean up
err = zipw.Close()
if err != nil {
    log.Fatal(err)
}
defer outFile.Close()

//Get the Content-Type of the file
//Create a buffer to store the header of the file in
FileHeader := make([]byte, 512)
//Copy the headers into the FileHeader buffer
outFile.Read(FileHeader)
//Get content type of file
 fmt.Println(reflect.TypeOf(outFile))
//Get the file size
FileStat, _ := outFile.Stat()                      //Get info from file
FileSize := strconv.FormatInt(FileStat.Size(), 10) //Get file size as a string

buffer := make([]byte, FileStat.Size())

outFile.Read(buffer)


//Send the headers
w.Header().Set("Content-Disposition", "attachment; filename="+"template.zip")
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Length", FileSize)
outFile.Seek(0, 0)
// io.Copy(w, buffer) //'Copy' the file to the client
w.Write(buffer)

推荐答案

  1. (主要问题):您将 outFile 的前512个字节 FileHeader 中,这意味着它们 not 读入 buffer ,这意味着文件的前512个字节不会发送到客户端.您执行了 Seek ,但是为时已晚,它变得不起作用了-此时已经设置了 buffer 的内容.您需要先移动搜索",或者写入两个缓冲区,或者只是删除不必要的 FileHeader 读取.

  1. (The primary problem): you Read the first 512 bytes of outFile into FileHeader, which means that they're not read into buffer, which means the first 512 bytes of the file aren't sent to the client. You do a Seek, but too late for it to be useful — the contents of buffer are already set at that point. You need to move the Seek earlier, or write both buffers, or just remove the unnecessary FileHeader read.

您的评论声称您这样做是为了获取文件的内容类型,但实际上从未使用过 FileHeader .为什么会这样呢?您知道文件的类型,您只是编写了文件.因此,不需要单独读取前512个字节.

Your comment claims that you do so to get the content-type of the file, but FileHeader is actually never used. And why would it be? You know what the type of the file is, you just wrote it. So the separate read of the first 512 bytes is unneeded.

实际上,这都是不需要的-使用 zip.Writer 写入文件,而不是在磁盘上创建文件,然后从磁盘中重新打开文件,然后将其读入文件中.字节数组,然后将该字节数组写入HTTP客户端,您可以直接将 zip.Writer 直接写入HTTP客户端(如果您不关心设置 Content-长度),或将其写入 bytes.Buffer ,然后将该缓冲区复制到HTTP客户端(如果准确的 Content-Length 对于您).

Actually, it's all unneeded — Instead of making a file on disk, using a zip.Writer to write to the file, re-opening the file from disk, reading it into a byte array, and then writing that byte array to the HTTP client, you could simply either have the zip.Writer write directly to the HTTP client (if you don't care about setting Content-Length), or have it write to a bytes.Buffer and then copy that buffer out to the HTTP client (if an accurate Content-Length is important to you).

第一个版本如下:

w.Header().Set("Content-Disposition", "attachment; filename=template.zip")
w.Header().Set("Content-Type", "application/zip")
zipw := zip.NewWriter(w)
// Your for loop to add items to the zip goes here.
//
zipw.Close() // plus error handling

第二个版本如下:

buffer := &bytes.Buffer{}
zipw := zip.NewWriter(buffer)
// Your for loop to add items to the zip goes here.
//
zipw.Close() // plus error handling
w.Header().Set("Content-Disposition", "attachment; filename=template.zip")
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Length", strconv.FormatInt(buffer.Length(), 10))
io.Copy(w, buffer) // plus error handling

这篇关于编辑内存中的zip文件并通过http响应返回它会导致文件损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆