我希望我的程序在文件开始下载之前有一个弹出的另存为窗口选项,但当我运行servlet时,它会自动开始下载文件。我在这里错过了什么?
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletOutputStream outputStream = response.getOutputStream();
FileInputStream fis=new FileInputStream("E:/sound.mp3");
response.setContentLength(fis.available());
response.setContentType("audio/basic");
response.addHeader("content-disposition", "attachment;filename=abc.mp3");
while(true){
int read = fis.read();
if(read==-1)break;
outputStream.write(read);
}
fis.close();
}
您的程序不是桌面/独立程序,因为它是在服务器上运行的servlet。当您在Eclipse中通过右键单击run as
->run on server
来运行它时,Eclipse实际上会打开一个网页来显示结果。因此,您的程序现在是一个Web应用程序,Eclipse(或它打开的页面)是客户端。客户端保存的是您发送的信息,而不是您的程序。明白了吗?
content-disposition
头只是用来建议下载的文件名。浏览器设置定义是否打开另存为窗口。你无法控制。
例如,在Google Chrome中,在Setting
/Advanced Setting
/Downloads
中,存在选项Ask where to save each file before downloading
。只有选中此选项,它才会打开所需的对话框。否则,它将保存在默认位置(也在浏览器设置中定义)。所有浏览器都有类似的选项。
还请注意,根据content-type
标头,浏览器将尝试显示内容,而不是下载。例如,浏览器将试图显示文本和html。但是,您可以通过将标题设置为不可显示的类型来强制下载:
response.setContentType("application/octet-stream");
如果您不想创建Web应用程序:由于您的程序运行在服务器上,它只需发送信息即可完成。是客户端程序决定如何处理它。在您目前的情况下,客户端是一个浏览器(或打开浏览器页面的Eclipse)。诸如content-disposition
报头之类的报头是针对浏览器的。如果你要创建自己的客户端(Swing客户端、Android应用程序、iPhone应用程序),而不是浏览器,那么客户端将从服务器接收信息,并决定如何处理(显示或以任何方式保存),甚至忽略HTTP标头。
尝试查看此处:http://www.java2s.com/Code/Java/Swing-JFC/DemonstrationofFiledialogboxes.htm
取出他们代码中的main语句,并将run(new FileChooserTest(), 250, 110);
放入您自己的代码中。如果我这样做,我会生成一个名为saveStatus
的int和3个等于0、1和2的韵母,分别命名为waiting
、save
和cancel
。然后,我会在您的其他程序中循环一段时间,看看saveStatus
是否等于waiting
,以暂停您的程序(但不暂停对话框)。然后,我会做一个if语句,看看saveStatus
是否等于save
。如果是,请下载,如果不是,请不要下载。就这么简单。
您的问题是Mime类型。某些类型(尤其是已知特定处理程序的类型)将被大多数浏览器直接下载。使用应用程序/二进制文件确实有所帮助,但即使这样,一些浏览器也可能被配置为下载它或在处置处理程序中解释文件扩展名。
我认为大多数解决方案在下载链接之前的页面上使用javascript。
您必须手动实现对话框,例如(http://docs.oracle.com/javase/7/docs/api/javax/swing/JFileChooser.html)。用户选择文件后,您将能够启动http请求下载(到servlet),并将文件保存到所需的路径。