FTPクライアントツールとして、IIS7サーバーマネージャーを推奨します。 このツールはFTPサイトの一括管理と定期的なアップロード・ダウンロード機能を提供します。 サーバー統合管理ツールとして、WindowsとLinuxシステム、VPSのサーバーを一括で管理できるのが最大の特徴です。 ウェブマスターおよびサーバー運用担当者の作業効率を大幅に向上させます。 また、IIS7サーバーマネージャーはVNCクライアントとしても機能し、サーバーを一元的に管理できるため非常に便利です。
FTPサーバーを構築してユーザーがアップロード・ダウンロードできるようにしましたが、ダウンロード中にテキストファイルや画像ファイル(txt、jpg、png、pdfなど)がブラウザ上で直接表示され、ダウンロードされない問題が発生しました。
以下の方法で解決策を見つけました:
最も簡単な方法: txtファイルを右クリックして「リンクを別名で保存」を選択すると、直接ダウンロードできます。
1:FTPディレクトリ内の.htaccessファイルを編集する方法 このファイルはファイルタイプのマッピングを行うもので、各ファイルタイプをoctet-streamタイプに変換することで、ブラウザによる解析を防ぎます。 しかし、FTPディレクトリに該当ファイルが見つからず、FileZillaを使用してサーバーに接続しても「隠しファイルを強制表示」オプションを有効にしてもファイルが表示されませんでした。 Apache専用のファイルであるとの情報があり、使用しているvsftpdサーバーでは存在しない可能性があるため、断念しました。
2:Ajaxを使用した方法 ファイルの出力ストリーム(OutputStream)をコールバック結果として返す方法です。 HTMLコードは以下の通り、バックエンドコードは方法4と同じです。
<html lang="en">
<head>
<script type="text/javascript" src="/js/jquery-3.0.0.min.js"></script>
<meta charset="UTF-8">
<title>タイトル</title>
<script>
function link() {
$.ajax({
type: "get",
url: "downloadFileByOutputStream",
data: {
"filename":'homepage.png'
},
async: true,
success: function (flag) {
if (flag != "") {
console.log(flag);
var obj = eval(flag);
localStorage['UsertypeSelect']=JSON.stringify(obj);
};
}
});
}
</script>
</head>
<body>
<a href="javascript:void(0)" onclick="link()">OutputStreamによるダウンロード</a>
</body>
</html>
実行後、データが文字化けし、eval(flag)による変換に失敗しました。
3:PrintWriterストリームを使用する方法 隠しフォームを使ってストリームをコールバックする方法です。 テキストファイルやドキュメントファイル(txt、docなど)は正常にダウンロード可能ですが、画像などのバイナリファイルはダウンロードできません。
フロントエンドコード:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
<script type="text/javascript" src="/js/jquery-3.0.0.min.js"></script>
<script>
function download(){
console.log('実行中');
downloadTemplate('/downloadFileByPrintWriter', 'filename', 'homepage.png');
}
function downloadTemplate(action, type, value){
console.log(action);
var form = document.createElement('form');
document.body.appendChild(form);
form.style.display = "none";
form.action = action;
form.id = 'download';
form.method = 'post';
var newElement = document.createElement("input");
newElement.setAttribute("type","hidden");
newElement.name = type;
newElement.value = value;
form.appendChild(newElement);
form.submit();
}
</script>
</head>
<body>
<span onclick="download()">PrintWriterによるダウンロード</span>
</body>
</html>
バックエンドコード:
/**
* 指定されたファイル名でダウンロードを行う
* 説明: FTPサーバーからファイルをダウンロード
* @param filename ダウンロードするファイル名
* @return
*/
@RequestMapping("/downloadFileByPrintWriter")
@ResponseBody
public String downloadFileByPrintWriter(HttpServletResponse response, String filename) throws IOException {
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);
ftp.login(username, password);
ftp.enterLocalPassiveMode();
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return "FTP接続なし";
}
ftp.changeWorkingDirectory(publicFilePath);
logger.debug("リモートパス" + publicFilePath);
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
logger.debug("リモートファイル名" + ff.getName());
if (ff.getName().equals(filename)) {
InputStream in = ftp.retrieveFileStream(ff.getName());
int len = 0;
byte[] buff = new byte[1024];
response.reset();
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
InputStreamReader inputStreamReader = new InputStreamReader(in);
PrintWriter fw = response.getWriter();
BufferedReader bf = new BufferedReader(inputStreamReader);
char[] chs = new char[1024];
String str=null;
while ((str = bf.readLine()) != null) {
fw.write(str);
fw.flush();
}
fw.flush();
in.close();
fw.close();
return "成功";
}
}
ftp.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return "ダウンロード失敗";
}
4:OutputStreamストリームを使用する方法(成功) 隠しフォームを使ってストリームをコールバックする方法で正常に動作しました。
HTMLコード:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
<script type="text/javascript" src="/js/jquery-3.0.0.min.js"></script>
<script>
function download(){
console.log('実行中');
downloadTemplate('/downloadFileByOutputStream', 'filename', 'homepage.png');
}
function downloadTemplate(action, type, value){
console.log(action);
var form = document.createElement('form');
document.body.appendChild(form);
form.style.display = "none";
form.action = action;
form.id = 'download';
form.method = 'post';
var newElement = document.createElement("input");
newElement.setAttribute("type","hidden");
newElement.name = type;
newElement.value = value;
form.appendChild(newElement);
form.submit();
}
</script>
</head>
<body>
<span onclick="download()">PrintWriterによるダウンロード</span>
</body>
</html>
バックエンドコード:
/**
* 指定されたファイル名でダウンロードを行う
* 説明: FTPサーバーからファイルをダウンロード
* @param filename ダウンロードするファイル名
* @return
*/
@RequestMapping("/downloadFileByOutputStream")
@ResponseBody
public String downloadFileByOutputStream(HttpServletResponse response, String filename) throws IOException {
logger.debug("OutputStreamによるダウンロード");
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);
ftp.login(username, password);
ftp.enterLocalPassiveMode();
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return "接続失敗";
}
ftp.changeWorkingDirectory(publicFilePath);
logger.debug("リモートパス" + publicFilePath);
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
logger.debug("リモートファイル名" + ff.getName());
if (ff.getName().equals(filename)) {
InputStream in = ftp.retrieveFileStream(ff.getName());
logger.debug(in.toString());
int len = 0;
byte[] buff = new byte[1024*1024];
response.reset();
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
OutputStream out=response.getOutputStream();
while((len=in.read(buff))!=-1){
logger.debug("OutputStreamとして書き出し");
out.write(buff, 0, len);
out.flush();
}
in.close();
out.close();
return "成功";
}
}
ftp.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return "失敗";
}