Golang实现CSV文件生成与下载功能

Golang实现CSV文件生成与下载功能 大家好!有人能帮我提供一些关于如何生成一个用于下载CSV的端点的文档、说明或示例吗?主要想法是我不想将文件保存在项目文件夹中。谢谢大家!

5 回复

谢谢。但我不是很理解CSV文件会被下载的方式。我的意思是,在其他编程语言中,我只需要在浏览器中输入URL,它就能工作,在Go语言中也是一样的吗?

更多关于Golang实现CSV文件生成与下载功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


为什么不使用 “encoding/csv” 直接写入到 http.ResponseWriter 呢?将内容类型头设置为 text/csv。

你可以编写你的端点,使其在接收到对你定义的 URL 的请求时执行。

func main() {
    fmt.Println("hello world")
}

主要想法是我不想将文件保存在项目文件夹中

将其保存在 temp 文件夹中,完成后删除它,类似这样:

	tmpDir := os.TempDir() + "\\myCSVfile"
	if p, err := os.Stat(tmpDir); os.IsNotExist(err) {
		err = os.Mkdir(tmpDir, 0755)
		defer os.RemoveAll(tmpDir)
		if err != nil {
			fmt.Printf("err 2: %v", err)
		} else {
                      /*********/
                       保存你的文件,并对其进行任何操作
                     /**********/
		}
	} else {
               os.RemoveAll(tmpDir)
	}

基于 @mje 所写的内容(根据您的描述,我认为这是正确的方法)进行扩展,这里有一个使用 encoding/csvhttp.ResponseWriter 写入数据的示例:

package main

import (
	"encoding/csv"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", serveDummyCSV)
	log.Fatal(http.ListenAndServe(":9090", nil))
}

func serveDummyCSV(w http.ResponseWriter, req *http.Request) {
	items := [][]string{
		{"UserID", "FullName", "Email"},           // Header
		{"1", "Jack Johnson", "jack@hotmail.com"}, // Items
		{"2", "Jill Smith", "jill@hotmail.com"},
		{"3", "James Murphy", "james@hotmail.com"},
	}

	// Set our headers so browser will download the file
	w.Header().Set("Content-Type", "text/csv")
	w.Header().Set("Content-Disposition", "attachment;filename=users.csv")
	// Create a CSV writer using our HTTP response writer as our io.Writer
	wr := csv.NewWriter(w)
	// Write all items and deal with errors
	if err := wr.WriteAll(items); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

将上述代码复制/粘贴到一个 main.go 文件中,然后运行 go run 命令。接着在浏览器中打开 localhost:9090,您的浏览器将正常下载 CSV 文件。写入/编码 CSV 是一件很简单的事情。让您的浏览器以文件形式下载 CSV 文件,只需要设置几个 HTTP 头部信息即可。

在Go中实现CSV生成和下载功能,可以直接在内存中处理数据并通过HTTP响应流式传输。以下是一个完整的示例:

package main

import (
    "encoding/csv"
    "net/http"
    "strconv"
)

func downloadCSV(w http.ResponseWriter, r *http.Request) {
    // 设置响应头,指定CSV文件下载
    w.Header().Set("Content-Type", "text/csv")
    w.Header().Set("Content-Disposition", "attachment; filename=data.csv")
    
    // 创建CSV写入器,直接写入HTTP响应
    writer := csv.NewWriter(w)
    defer writer.Flush()
    
    // 写入CSV表头
    headers := []string{"ID", "Name", "Email", "Age"}
    if err := writer.Write(headers); err != nil {
        http.Error(w, "Failed to write CSV header", http.StatusInternalServerError)
        return
    }
    
    // 示例数据 - 这里可以替换为你的实际数据源
    data := [][]string{
        {"1", "John Doe", "john@example.com", "30"},
        {"2", "Jane Smith", "jane@example.com", "25"},
        {"3", "Bob Johnson", "bob@example.com", "35"},
    }
    
    // 写入数据行
    for _, row := range data {
        if err := writer.Write(row); err != nil {
            http.Error(w, "Failed to write CSV row", http.StatusInternalServerError)
            return
        }
    }
}

// 动态生成数据的示例
func downloadDynamicCSV(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/csv")
    w.Header().Set("Content-Disposition", "attachment; filename=users.csv")
    
    writer := csv.NewWriter(w)
    defer writer.Flush()
    
    // 写入表头
    writer.Write([]string{"UserID", "Username", "Status", "Score"})
    
    // 模拟从数据库或其他数据源获取数据
    for i := 1; i <= 100; i++ {
        row := []string{
            strconv.Itoa(i),
            "user" + strconv.Itoa(i),
            "active",
            strconv.Itoa(i * 10),
        }
        writer.Write(row)
    }
}

func main() {
    http.HandleFunc("/download/csv", downloadCSV)
    http.HandleFunc("/download/dynamic-csv", downloadDynamicCSV)
    http.ListenAndServe(":8080", nil)
}

对于大型数据集,可以使用缓冲和流式处理:

func downloadLargeCSV(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/csv")
    w.Header().Set("Content-Disposition", "attachment; filename=large_data.csv")
    
    writer := csv.NewWriter(w)
    defer writer.Flush()
    
    // 写入表头
    writer.Write([]string{"Index", "Value", "Timestamp"})
    
    // 流式生成大量数据
    for i := 0; i < 1000000; i++ {
        row := []string{
            strconv.Itoa(i),
            "Value" + strconv.Itoa(i),
            strconv.FormatInt(time.Now().UnixNano(), 10),
        }
        
        if err := writer.Write(row); err != nil {
            http.Error(w, "Failed to write CSV", http.StatusInternalServerError)
            return
        }
        
        // 每1000行刷新一次缓冲区
        if i%1000 == 0 {
            writer.Flush()
            if err := writer.Error(); err != nil {
                http.Error(w, "CSV write error", http.StatusInternalServerError)
                return
            }
        }
    }
}

如果需要处理结构化数据,可以使用结构体切片:

type Product struct {
    ID    int
    Name  string
    Price float64
    Stock int
}

func downloadProductsCSV(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/csv")
    w.Header().Set("Content-Disposition", "attachment; filename=products.csv")
    
    writer := csv.NewWriter(w)
    defer writer.Flush()
    
    // 写入表头
    writer.Write([]string{"ID", "Name", "Price", "Stock"})
    
    // 模拟产品数据
    products := []Product{
        {1, "Laptop", 999.99, 50},
        {2, "Mouse", 25.50, 200},
        {3, "Keyboard", 75.00, 150},
    }
    
    for _, p := range products {
        row := []string{
            strconv.Itoa(p.ID),
            p.Name,
            strconv.FormatFloat(p.Price, 'f', 2, 64),
            strconv.Itoa(p.Stock),
        }
        writer.Write(row)
    }
}

这些示例展示了如何在不保存文件到磁盘的情况下,直接在HTTP响应中生成和传输CSV数据。

回到顶部