搭建了一个ftp服务器,供用户进行上传下载,在下载过程中发现,一些文件,例如txt,jpg,png,pdf等直接被浏览器解析了。在浏览器中显示其内容,没有下载。

下面通过网上查询得到一些解决方法:

最简单的方法:

在txt文档上面,点击右键》链接另存为    就可以直接下载。

1:修改ftp目录下的.htacess文件,这个文件主要做一些类型映射,使各个文件类型映射为  octet-stream 类型,这样浏览器就不能解析了。

但是,我没有在ftp目录下发现该文件,通过filezilla连接服务器, filezilla>服务器>强制显示隐藏文件 ,也没有发现该文件。听说该文件是apache独有的,我用的是vsftpd服务器,不知道是否存在不一致,于是放弃。

2:第二种方法

使用ajax请求,将文件输出流(OutputStream)作为回调结果返回。

html代码,   后台代码同第4中方法。

<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript" src="/js/jquery-3.0.0.min.js"></script>
<meta charset="UTF-8">
<title>Title</title> <script>
function link() {
$.ajax({
type: "get", //请求方式
url: "downloadFileByOutputStream", //请求路径
data: {
"filename":'homepage.png' //请求参数
},
async: true, //异步,(同步已经废弃,会报错)。
success: function (flag) { //请求成功,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等字符文件能够下载,但是图片等字节文件不能下载。

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>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){ //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'; //表单id
form.method = 'post'; //请求方式 var newElement = document.createElement("input"); //创建元素,类型为input
newElement.setAttribute("type","hidden"); //隐藏
newElement.name = type; //元素名为type
newElement.value = value; //元素值 value
form.appendChild(newElement);
form.submit(); //提交
}
</script>
</head>
<body> <span onclick="download()">客户端下载PrintWriter</span> </body>
</html>

后台代码:

   /**
* 根据给定的文件名进行下载
* Description: 从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(); //将ftp设置为被动模式。否则不成功。 reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return "ftp无连接";
}
ftp.changeWorkingDirectory(publicFilePath);// 转移到FTP服务器目录
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()); //读取ftp服务器文件,返回输入流
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(); //得到response的字符打印流 //创建一个rd的字符留缓冲区,将字符装载入缓冲区中
BufferedReader bf = new BufferedReader(inputStreamReader);
char[] chs = new char[1024];
// while ((len = bf.read(chs)) != 0) {
// logger.debug("向fw写入");
//// fw.write(chs, 0, len);
// }
String str=null;
while ((str = bf.readLine()) != null) {
fw.write(str); //将ftp输入流写出到printWriter
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代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>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>

后台代码:

  /**
* 根据给定的文件名进行下载
* Description: 从FTP服务器下载文件
* @param filename 要下载的文件名
* @return
*/
@RequestMapping("/downloadFileByOutputStream")
@ResponseBody
public String downloadFileByOutputStream(HttpServletResponse response, String filename) throws IOException {
logger.debug("下载ByOutputStream");
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
ftp.enterLocalPassiveMode(); //将ftp设置为被动模式。否则不成功。
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return "连接失败";
}
ftp.changeWorkingDirectory(publicFilePath);// 转移到FTP服务器目录
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");
//Name the file
response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
// response.addHeader("Content-Length", out..ToString());
OutputStream out=response.getOutputStream(); //响应输出字节流 // OutputStream out = new PipedOutputStream();
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 "失败";
}

解决下载ftp文件过程中,浏览器直接解析文件(txt,png等)的问题的更多相关文章

  1. 编译过程中,termcap.h 文件找不到路径 licli.a终于生成

    编译过程中,termcap.h      文件找不到路径   查看是linux  源码下找不到termcap.h文件   安装了所有关于*cap*的源码包也不起作用     今天终于解决了这个问题,搜 ...

  2. Android技巧分享——如何用电脑下载在Google play中应用的apk文件

    [Android技巧分享系列] 1.Android技巧分享——让官方模拟器和genymotion虚拟机飞起来 2.Android技巧分享——如何用电脑下载在Google play中应用的apk文件 G ...

  3. 使用ftp读取文件夹中的多个文件,并删除

    public class FTPUtils { private static final Logger LOG = LoggerFactory.getLogger(FTPUtils.class); / ...

  4. 用字符流实现每个文件夹中创建包含所有文件信息的readme.txt

    package com.readme; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; i ...

  5. 在文件夹中 的指定类型文件中 查找字符串(CodeBlocks+GCC编译,控制台程序,仅能在Windows上运行)

    说明: 程序使用 io.h 中的 _findfirst 和 _findnext 函数遍历文件夹,故而程序只能在 Windows 下使用. 程序遍历当前文件夹,对其中的文件夹执行递归遍历.同时检查遍历到 ...

  6. 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览

    ### 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览 http://segmentfault.com/a/1190000002583569

  7. 【源码】rm zip 删除文件夹中大量的小文件 百万 扫描文件时间

    rm  删除文件夹中大量的小文件 百万 迟迟未删除 在扫描文件? rm删除命令源码分析 - ty_laurel的博客 - CSDN博客 https://blog.csdn.net/ty_laurel/ ...

  8. 在存放源程序的文件夹中建立一个子文件夹 myPackage。例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage)。在 myPackage 包中创建一个YMD类,该类具有计算今年的年份、可以输出一个带有年月日的字符串的功能。设计程序SY31.java,给定某人姓名和出生日期,计算该人年龄,并输出该人姓名、年龄、出生日期。程序使用YM

    题目补充: 在存放源程序的文件夹中建立一个子文件夹 myPackage.例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage).在 m ...

  9. java基础 File 递归删除文件夹中所有文件文件夹 目录(包含子目录)下的.java文件复制到e:/abc文件夹中, 并统计java文件的个数

    File 递归删除文件夹中所有文件文件夹 package com.swift.kuozhan; import java.io.File; import java.util.Scanner; /*键盘录 ...

随机推荐

  1. Java 9的日期时间格式化趋近Unicode区域设置标准

        1.JDK-8148947,DataTimeFormatter的模式字母“g”:正如在LDML中定义的,字母“g”指代一个“简化儒略日期”,简化儒略日期与正常儒略日期的差别在于:(1)简化儒略 ...

  2. linux,crontab定时任务中为脚本指定使用参数,crontab的脚本中是否可以带参数

    需求描述: 今天在写脚本的时候,脚本的运行需要给出几个参数,那么就考虑 在crontab写定时任务的时候,是否也是能够在脚本中,增加参数呢, 因为以前没有这么用过,所以呢,就进行一次测试. 测试过程: ...

  3. 第四章 Spring.Net 如何管理您的类___对象、对象工厂和应用程序上下文

    在前面一章我们介绍了依赖注入,控制反转的概念,以及自己动手搭建了一下Spring.Net的环境.通过这些操作,我们知道了Spring.Net 的核心是使用依赖注入或控制反转这种思想来管理业务对象,降低 ...

  4. day10<面向对象+>

    面向对象(package关键字的概述及作用) 面向对象(包的定义及注意事项) 面向对象(带包的类编译和运行) 面向对象(不同包下类之间的访问) 面向对象(import关键字的概述和使用) 面向对象(四 ...

  5. python2.0_s12_day10_rabbitMQ使用介绍

    RabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列(M ...

  6. window 后台执行 redis(隐藏窗口)

    方法是在知乎上看的,链接:https://www.zhihu.com/question/22771030 实现方法是利用一个vbe脚本去运行一个bat脚本,在bat脚本里启动exe软件 PS:要想启动 ...

  7. INSTALL_FAILED_INVALID_APK

    在项目中无意中把APP只写成了 xxx  没有xxx.xxx.xxx  掉坑里了,找了好久,给大家提不醒

  8. Android中的动画,选择器,样式和主题的使用

    一.动画: 1.动画的分类: 1).Tween动画:这种实现方式可以使视图组件移动.放大.缩小以及产生透明度的变化: 2).Frame动画:传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影. ...

  9. IOS深入学习(20)之Object modeling

    1 前言 本节简单的介绍了对象建模,以及需要注意的事项. 2 详述 对象建模是对设计通过一个面向对象应用检测和操作服务的对象或者类的加工.许多模型技术是可能的:Cocoa开发环境不推荐歧义性. 典型地 ...

  10. 谈谈java中的构造函数

    from 本篇博文主要是为新手.对java语言感兴趣的人和那些没有系统学习过java基础知识的人进行一个总结,在文章中对构造函数进行了较为详细的说明和讨论,也包含了我个人对于java面向对象中构造函数 ...