您的位置:首页 > Web前端 > JavaScript

由response.setContentType()方法开始谈JSP/Servelt上传下载文件

2015-02-04 10:20 519 查看
序号
内容类型
文件扩展名
描述
1
application/msword
doc
Microsoft Word
2
application/octet-stream bin
dms lha lzh exe class
可执行程序
3
application/pdf
pdf
Adobe Acrobat
4
application/postscript
ai eps ps
PostScript
5
appication/powerpoint
ppt
Microsoft Powerpoint
6
appication/rtf
rtf
rtf 格式
7
appication/x-compress
z
unix 压缩文件
8
application/x-gzip
gz
gzip
9
application/x-gtar
gtar
tar 文档 (gnu 格式 )
10
application/x-shockwave-flash
swf
MacroMedia Flash
11
application/x-tar
tar
tar(4.3BSD)
12
application/zip
zip
winzip
13
audio/basic
au snd
sun/next 声音文件
14
audio/mpeg
mpeg mp2
Mpeg 声音文件
15
audio/x-aiff
mid midi rmf
Midi 格式
16
audio/x-pn-realaudio
ram ra
Real Audio 声音
17
audio/x-pn-realaudio-plugin
rpm
Real Audio 插件
18
audio/x-wav
wav
Microsoft Windows 声音
19
image/cgm
cgm
计算机图形元文件
20
image/gif
gif
COMPUSERVE GIF 图像
21
image/jpeg
jpeg jpg jpe
JPEG 图像
22
image/png
png
PNG 图像
text/html HTML
text/plain TXT
text/xml XML
text/json json字符串
此外不同浏览器下对同一个文件上传后获取到的类型可能不同。

1、文件下载:
文件下载的关键代码在于:
[align=left] response.setHeader("Content-disposition", "attachment;filename="[/align]
[align=left] + "test.rar");[/align]
[align=left] // set the MIME type.[/align]
[align=left] response.setContentType("application/x-tar");[/align]
[align=left] response.setHeader("Content_Length", length);[/align]
[align=left] 即通过设置HttpServletResponse的各个属性来实现。[/align]
[align=left] [/align]
文件下载有一个最容易犯错的地方是直接通过:<a href="test.txt">Download</a> 来实现,没有这么简单的。如果你是通过类似这样的路径:file:///C:/test/down.html 假设前面这行代码包含在 download.html中,那么你或许可以很顺利地得到,而如果这个html文件(或JSP文件)在Web服务器中比如Tomcat,那么你点击这个将没有反应的。这时查看源代码会发现链接内容变为: http://localhost:8080/file:///c:/test/down.html ,我猜测可能是这样:当<a>标签中指定的href值为相对路径时,Web服务器会默认在这个相对路径前加上服务器根路径。

[align=left] 是不是有点晕?不要紧。其实搞懂这么一个问题就行了。文件下载时,文件是存在Web服务器的某个目录下的,或者说存在服务器的磁盘上的,那么我们可以在Servlet中通过Java的File及相关API访问文件,因为Servlet是在服务器端执行的。而如果呈现给客户端的页面中有这么一个链接:[/align]
<a href="c:/test.txt">download it!</a>

[align=left] 你说能正常获取到服务器C盘的test.txt文件嘛?显然获取不到的。因为现在是在客户端,所以href被Web服务器解析成 http://localhost:8080/file:///c:/test.txt 返回给客户端。[/align]

[align=left] 那么该如何实现文件下载?不能直接使用包含盘符的文件路径表示href,但是盘符路径可以用在Servelt中构造File对象,即将文件加载到Web服务器内存中,然后写到响应流中返回给客户端,即实现了。[/align]
[align=left] [/align]
[align=left] 下面是代码演示:[/align]
[align=left] 主要包含 index.jsp、访问路径为/loadFile的Servelt(名称为LoadFile),至于web.xml配置Servelt省略。[/align]

[html]
view plaincopy

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>download page</title>
</head>
<body>
<a href="loadFile?filename=test.txt&path="+escape("C:/test.txt")>Download It!</a>
</body>
</html>

LoadFile类如下:

[java]
view plaincopy

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoadFile extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {

[java]
view plaincopy

String filename = request.getParameter("filename");

[java]
view plaincopy

String path = request.getParameter("path");
OutputStream o = response.getOutputStream();
byte b[] = new byte[1024];
// the file to download.
File fileLoad = new File(path);
// the dialogbox of download file.
response.setHeader("Content-disposition", "attachment;filename="
+ "test.txt");
// set the MIME type.
response.setContentType("text/html");
// get the file length.
long fileLength = fileLoad.length();
String length = String.valueOf(fileLength);
response.setHeader("Content_Length", length);
// download the file.
FileInputStream in = new FileInputStream(fileLoad);
int n = 0;
while ((n = in.read(b)) != -1) {
o.write(b, 0, n);
}
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
doGet(request, response);
}
}

[align=left] 即OK了。[/align]

[align=left]2. 文件上传[/align]
[align=left] 虽然文件上传和下载都能通过开源组件来实现,但如果要自己实现的话还是费一番功夫的。文件上传一般是通过<form>表单结合<input type="file">来实现的。最后在服务端的Servlet中通过requst获取输入流,然后写到服务器磁盘文件中去。虽然原理清楚了,但是是否就可以直接像下面这样写呢?[/align]

[java]
view plaincopy

test.jsp
<%@page contentType="text/html;charset=GB2312"%>
<html>
<body>
选择要上传的文件:<br />
<form action="accept.jsp" method="post" enctype="multipart/form-data">
<input type="file" name="boy" size="38">
<br />
<input type="hidden" id="tt" name="t" value="1" />
<input type="submit" id="gg" name="g" value="提交" />
</form>
</body>
</html>

[java]
view plaincopy

[java]
view plaincopy

accept.jsp
<%@page contentType="text/html;charset=GB2312"%>
<%@ page import="java.io.*"%>
<HTML>
<BODY>
<%
//经测试,说明:ServletInputStream类中的readLine(byte[] b, int off, int len)
//其中参数 byte[] b 起缓冲作用,此方法一次读取一行,但如果 byte[] b 定义的大小,比要读取的一行需占用的空间要小,则
//该方法只读取 byte[] b 指定的大小;再次读取时会继续接着上次未读完的读取;返回值 :返回实际读取的字节数,当读到文档流的
//最后时返回-1。
try{
ServletInputStream in=request.getInputStream();
File f=new File("c:\\test","a.txt");
FileOutputStream o=new FileOutputStream(f);

//如果byte b[]=设置的值太短的话(假如设置为2),那么在 应用的 上传操作时会有影响,具体表现为无法解析文档路径等相关信息
byte b[]=new byte[2046];
int n;
int i = 0;
while((n=in.readLine(b,0,b.length))!=-1)//ServletInputStream.readLine方法是逐行读取的。当它读完整个文件,返回-1,一般情况下返回读取的字节数
{
i++;
System.out.println("------"+i);
o.write(b,0,n);
}
o.close();
in.close();
}catch(IOException e){
e.printStackTrace();
}
out.print("文件已经上传");
%>
<a href="c:\\test\\a.txt">查看结果</a>
</body>
</HTML>

我上传一个test.txt文件,其内容为3行 Hello World!。之后打开C:\\test\a.txt,内容如下:

[html]
view plaincopy

-----------------------------7db2611a404a4
Content-Disposition: form-data; name="boy"; filename="C:\Users\xijiang\Desktop\test.txt"
Content-Type: text/plain

Hello World!
Hello World!
Hello World!
-----------------------------7db2611a404a4
Content-Disposition: form-data; name="t"

1
-----------------------------7db2611a404a4
Content-Disposition: form-data; name="g"

提交
-----------------------------7db2611a404a4--

可以很明显看到内容不是我们预期的只有三行Hello World!,还多了其他的表单属性值。观察这个文件的内容格式,可以大概看出,

[html]
view plaincopy

-----------------------------7db2611a404a4

[html]
view plaincopy

是字段间隔符。

[html]
view plaincopy

<pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; ">-----------------------------7db2611a404a4--</pre>
<pre></pre>
<pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; "> 是结束符。</pre><pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; "> <input type="file">对应的值表示为:</pre><pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; "><pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; ">-----------------------------7db2611a404a4
Content-Disposition: form-data; name="boy"; filename="C:\Users\jxq\Desktop\test.txt"
Content-Type: text/plain

Hello World!
Hello World!
Hello World!</pre><pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; "> 即第一行是 Content-Disposition、name和客户端上传的文件的目录,第二行是上传的文件类型,第三行是空行,接下来是文件内容。</pre><pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; "> 而表单提交的其他属性值则是通过 Content-Disposition: from-dat; name=xx 来表示。</pre><pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; "> 所以为了获取上传的文件的真正内容,我们不能简单地读取从request获得的输入流,必须进一步解析。</pre>
<pre></pre>
<pre name="code" class="html" style="background-color: rgb(255, 255, 255); text-align: -webkit-left; "></pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>

参考链接:
/article/2440419.html
/article/4381675.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: