golang api图像下载中损坏的图像文件

问题描述 投票:0回答:1

我正在使用golang构建一个简单的测试API,用于上传和下载图像文件(PNG,JPEG,JPG):

/ pic [POST]用于上传图像并将其保存到文件夹; / pic [GET],用于将图像下载到客户端。

我已经成功构建了/ pic [POST],并且图像已成功上传到服务器的文件。我可以在存储文件夹中打开文件。 (在Windows localhost服务器和ubuntu服务器中)

但是,当我构建/ pic [GET]来下载图片时,我可以将文件下载到客户端(我的计算机),但是自从尝试使用其他图像打开它以来,下载的文件已被破坏了查看器(如Gallery或Photoshop)显示为“我们似乎不支持此文件格式”。因此,似乎下载未成功。

邮递员结果:enter image description here

在图库中打开文件:enter image description here关于为什么会发生这种情况以及如何解决的任何想法?

用于下载图片的golang代码如下(省略错误处理):

func PicDownload(w http.ResponseWriter, r *http.Request){

   request := make(map[string]string)
   reqBody, _ := ioutil.ReadAll(r.Body)
   err = json.Unmarshal(reqBody, &request)
   // Error handling

   file, err := os.OpenFile("./resources/pic/" + request["filename"], os.O_RDONLY, 0666)
   // Error handling

   buffer := make([]byte, 512)
   _, err = file.Read(buffer)
   // Error handling

   contentType := http.DetectContentType(buffer)

   fileStat, _ := file.Stat()

   // Set header
   w.Header().Set("Content-Disposition", "attachment; filename=" + request["filename"])
   w.Header().Set("Content-Type", contentType)
   w.Header().Set("Content-Length", strconv.FormatInt(fileStat.Size(), 10))

   // Copying the file content to response body
   io.Copy(w, file)

   return
}
image api file go download
1个回答
1
投票

当您从文件中读取前512个字节以确定内容类型时,基础文件流指针将向前移512个字节。当您以后调用io.Copy时,将从该位置继续读取。

有两种方法可以纠正此问题。

首先是在调用file.Seek(0, io.SeekStart)之前先调用io.Copy()。这会将指针放回到文件的开头。此解决方案需要最少的代码量,但意味着两次从文件读取相同的512字节,这会导致一些开销。

[第二种解决方案是使用buffer := make([]byte, fileStat.Size()创建一个包含整个文件的缓冲区,并使用该缓冲区进行http.DetectContentType()调用并写入输出(使用w.Write(buffer)而不是io.Copy()来写。)这种方法可能有一次将整个文件加载到内存中的缺点,这对于非常大的文件来说并不理想(io.Copy使用32KB块而不是加载整个文件)。

注意:正如Peter在评论中提到的,您必须确保用户不能通过发布../../或其他文件名来遍历您的文件系统。

© www.soinside.com 2019 - 2024. All rights reserved.