ใช้ Content-Disposition header ทำให้ browser download ไฟล์แทนที่จะเปิดใน browser
Tags: go, http, programming
Published: 2021-03-04 13:38:32

วันก่อนต้องเขียน API endpoint นึงแต่ไม่ใช่ ตอบกลับเป็น JSON แต่จะตอบเป็น content ของ PDF แทน ซึ่งเราอยากให้เมื่อกดลิ้งมาที่ endpoint นี้จากทาง browser แล้วให้ browser นั้นโหลดไฟล์ แทนที่จะเปิดไฟล์ผ่าน browser

วิธีที่ช่วยได้คือกำหนดค่าให้กับ header ที่ชื่อ `Content-Disposition` 

เรามาดูตัวอย่างธรรมดากันก่อนแบบไม่ใช้ `Content-Disposition` ว่าพฤติกรรมของ browser นั้นเป็นยังไง ตัวอย่างเป็นโค้ด Go

ถ้าเรามีโค้ดแบบนี้

```go
package main

import (
	"log"
	"net/http"
	"os"
)

func main() {
	http.HandleFunc("/cat.jpg", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "image/jpeg")
		b, err := os.ReadFile("image.jpg")
		if err != nil {
			log.Fatal(err)
		}
		w.Write(b)
	})

	http.HandleFunc("/index.html", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		b, err := os.ReadFile("index.html")
		if err != nil {
			log.Fatal(err)
		}
		w.Write(b)
	})

	http.ListenAndServe(":8000", nil)
}
```

และส่วนของ `index.html` เป็นแบบนี้

```html
<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Load</title>
</head>
<body>
        <a href="/cat.jpg">Download Picture</a>
</body>
</html>

```

เมื่อรันโค้ดแล้วเข้าไปที่ `localhost:8000/index.html` จะเจอลิ้ง download แบบนี้

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1op748oqi5csr7lcqo9.png)

และเมื่อเรากดลิ้งจะเห็นว่า browser นั้นเปิดใน browser เลยแบบนี้

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sc2habqepqs0tv5cy8vl.png)

ทีนี้ถ้าเราต้องการให้ browser โหลดไฟล์แทนเราสามารถกำหนด header `Content-Disposition` ไปแบบนี้

```go
package main

import (
	"log"
	"net/http"
	"os"
)

func main() {
	http.HandleFunc("/cat.jpg", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "image/jpeg")
		w.Header().Set("Content-Disposition", `attachment; filename="cat.png"`)
		b, err := os.ReadFile("image.jpg")
		if err != nil {
			log.Fatal(err)
		}
		w.Write(b)
	})

	http.HandleFunc("/index.html", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		b, err := os.ReadFile("index.html")
		if err != nil {
			log.Fatal(err)
		}
		w.Write(b)
	})

	http.ListenAndServe(":8000", nil)
}

```

ส่วนค่าของ header คือกำหนดเป็น 

```
`attachment; filename="cat.png"`
```

ตรง `filename` คือกำหนดชื่อไฟล์ที่จะให้ browser ใช้เซฟตอน download นั่นเอง

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pnfjpe0rd3h2i8q00ov9.png)

## ขอฝาก Buy Me a Coffee
สำหรับท่านใดที่อ่านแล้วชอบโพสต์ต่างๆของผมที่นี่ ต้องการสนับสนุนค่ากาแฟเล็กๆน้อยๆ สามารถสนับสนุนผมได้ผ่านทาง Buy Me a Coffee คลิ๊กที่รูปด้านล่างนี้ได้เลยครับ

<a href="https://www.buymeacoffee.com/weerasak" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>

ส่วนท่านใดไม่สะดวกใช้บัตรเครดิต หรือ Paypal สามารถสนับสนุนผมได้ผ่านทาง PromptPay โดยดู QR Code ได้จากโพสต์ที่พินเอาไว้ได้ที่ Page DevDose ครับ https://web.facebook.com/devdoseth

ขอบคุณครับ 🙏