ป้ายกำกับ

วันอังคารที่ 22 กันยายน พ.ศ. 2558

การบังคับให้ Browser บันทึกไฟล์

ในบางครั้งที่เราทำลิ้งค์ไปยังไฟล์ใดๆ โดยเฉพาะไฟล์ที่เปิดใช้งานได้ด้วย browser เช่น ไฟล์เสียง และ ไฟล์วีดีโอ แต่ในบางกรณีก็มีข้อจำกัด เช่น server ของเราอาจจะไม่สามารถให้บริการไฟล์ได้อย่างต่อเนื่อง (streaming) หรือผู้ใช้บางรายใช้ browser ที่ไม่รองรับ format ของไฟล์บางชนิด เราจึงอาจจะต้องการให้ผู้ใช้บันทึกไฟล์ไว้ แทนที่จะเปิดดูในขณะนั้น

การจะใช้คำสั่ง JavaScript จัดการให้ browser บันทึกไฟล์อัตโนมัติ ก็จะทำไม่ได้ เนื่องจากจะติดปัญหาเรื่องความปลอดภัย เพราะหากเปิดช่องตรงนี้ไว้ จะทำให้เว็ปที่ไม่ปลอดภัยสามารถแอบปล่อยไวรัสไว้ในเครื่องของผู้ใช้งานได้ง่ายๆ

วิธีการที่ดีที่สุดคือการใช้ Content-Disposition ใน header ของ HTTP โปรโตคอล โดยวิธีการนี้ต้องอาศัยการเขียนโปรแกรมทางฝั่ง server เพื่อรองรับการตอบกลับแบบนี้ ซึ่งทำได้ทุกภาษาเช่น PHP, ASP.NET, Perl/CGI หรือ JSP เป็นต้น แต่ในกรณีทั่วไปที่เราใช้บริการฟรี server เราอาจจะไม่สามารถเขียนโปรแกรมใดๆได้ จึงอาจจะเป็นข้อจำกัดของวิธีการนี้

รูปแบบของ Content-Disposition

รูปแบบของ Content-Disposition สำหรับ HTTP ได้กำหนดไว้ใน RFC6266 (อ้างอิง 1) โดยสรุปคือ
Content-Disposition: <value> [; <param>]
โดยที่ <value> มีค่าเป็น (ไม่สนใจตัวอักษรใหญ่-เล็ก)

  1. inline หมายถึง แสดงผลอัตโนมัติ โดยทั่วไปไม่ต้องระบุก็จะแสดงอัตโนมัติเป็นปกติ
  2. attachment หมายถึง ผู้ใช้ควบคุมการแสดงผล
ซึ่งหมายความว่า หากต้องการบังคับให้ผู้ใช้บันทึกไฟล์ เราจะต้องกำหนด Content-Disposition มีค่าเป็น attachment นั่นเอง


ส่วน <param> มีค่าเป็น (ไม่สนใจตัวอักษรใหญ่-เล็ก)

  1. filename = <name> หมายถึงชื่อไฟล์ <name>
  2. filename* = <name> หมายถึงชื่อไฟล์ <name> ที่เข้ารหัสแบบที่ไม่ใช่ ISO-8859-1
หมายเหตุ: บาง borwser อาจจะไม่รองรับค่า filename* จึงควรจะส่งค่าทั้งสองแบบ
Content-Disposition: attachment;
                          filename="EURO rates";
                          filename*=utf-8''%e2%82%ac%20rates

ตัวอย่าง

ภาษา PHP

<?php
header('Content-disposition: attachment; filename=movie.mpg');
header('Content-type: video/mpeg');
?>

ภาษา JSP

<% //Set the headers.
response.setHeader("Content-Disposition", "attachment; filename=downloaded.pdf");
response.setContentType("application/x-download");
%>

อ้างอิง

  1. IETF, RFC6266
  2. W3, HTTP/1.1 Appendices
  3. IANA, Content Disposition Values and Parameters