package jp.co.areaweb.tools.servlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * サーバ上のファイル（やデータベース等に保存してあるデータ）をブラウザに送る場合は、適切なコンテントタイプをセットした
 * 後にファイル内容を送信します。
 * その際、ブラウザ側でどのように処理して欲しいかによって、「inline」と「attachment」の２つの形式があります。
 * inlineは送信内容がブラウザによってただちに表示されることを指し(*1)、attachmentはブラウザによってファイルに
 * 保存されます。
 */
@SuppressWarnings("serial")
public class FileDownloadServlet extends HttpServlet {
	// 拡張子contentType対応テーブル
	private final static String contentTypeTable[][] = {
		{"jpg", "image/pjpeg"},
		{"gif", "image/gif"},
		{"txt", "text/plain"},
		{"csv", "text/plain"},
		{"xml", "text/plain"},
		{"xsl", "text/plain"},
		{"xls", "application/vnd.ms-excel"}
	};
	private final static int EXTENTION=0;
	private final static int CONTENT_TYPE=1;

	/**
	 * パラメータ：
	 * 	fileName	クライアント側の文字エンコーディングのままのファイル名
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// ファイル読み込み用バッファ
		byte buffer[]  = new byte[4096];
		
		// クライアント側の文字エンコーディングのままのファイル名
		String fileName1 = request.getParameter("fileName");
		// Unicodeに変更されたファイル名
		
		// 拡張子からcontentTypeを獲得
		String contentType = getContentType(fileName1);
		
		// contentTypeを出力
		response.setContentType(contentType);
		
		File file = new File(fileName1);
		// ファイル名の送信(attachment部分をinlineに変更すればインライン表示)
		String fileName2 = new String(file.getName().getBytes("Windows-31J"), "ISO8859_1");
		//response.setCharacterEncoding("Windows-31J");
		response.setHeader("Content-disposition", "attachment; filename=\""+ fileName2 +"\"");
		// ファイル内容の出力
		ServletOutputStream out = response.getOutputStream();
		FileInputStream fin = new FileInputStream(file);
		int size;
		while((size = fin.read(buffer))!=-1) {
			out.write(buffer,0, size);
		}
		fin.close();
		out.close();
	}

	/**
	 *  ファイル名から拡張子を取り出す
	 */
	private String getExtention(String fileName) {
		int idx = fileName.lastIndexOf('.');
		if (idx!=-1) {
			return fileName.substring(idx+1, fileName.length());
		}
		return "";
	}

	/**
	 *  拡張子からcontentTypeを取り出す
	 */
	private String getContentType(String fileName) {
		String extention = getExtention(fileName);
		for (int j=0; j < contentTypeTable.length; j++) {
			if (contentTypeTable[j][EXTENTION].equalsIgnoreCase(extention)) {
				return contentTypeTable[j][CONTENT_TYPE];
			}
		}
		return "application/octet-stream";
	}
}
