http://blog.csdn.net/feichexia/article/details/7105741#

  1. 常见的MIME类型如下表:  
   常见的MIME类型如下表:

序号

内容类型

文件扩展名

描述

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、文件下载:

   文件下载的关键代码在于:

  response.setHeader("Content-disposition", "attachment;filename="
              + "test.rar");
  // set the MIME type.
  response.setContentType("application/x-tar");
  response.setHeader("Content_Length", length);
  即通过设置HttpServletResponse的各个属性来实现。
  
   文件下载有一个最容易犯错的地方是直接通过:<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服务器会默认在这个相对路径前加上服务器根路径。

   是不是有点晕?不要紧。其实搞懂这么一个问题就行了。文件下载时,文件是存在Web服务器的某个目录下的,或者说存在服务器的磁盘上的,那么我们可以在Servlet中通过Java的File及相关API访问文件,因为Servlet是在服务器端执行的而如果呈现给客户端的页面中有这么一个链接:
   <a href="c:/test.txt">download it!</a>
   你说能正常获取到服务器C盘的test.txt文件嘛?显然获取不到的。因为现在是在客户端,所以href被Web服务器解析成 http://localhost:8080/file:///c:/test.txt 返回给客户端。

   那么该如何实现文件下载?不能直接使用包含盘符的文件路径表示href,但是盘符路径可以用在Servelt中构造File对象,即将文件加载到Web服务器内存中,然后写到响应流中返回给客户端,即实现了。
  
   下面是代码演示:
   主要包含 index.jsp、访问路径为/loadFile的Servelt(名称为LoadFile),至于web.xml配置Servelt省略。
  1. <html>  
  2. <head>  
  3.     <meta http-equiv="Content-Type" content="text/html; charset=GB18030">  
  4.     <title>download page</title>  
  5. </head>  
  6. <body>  
  7.     <a href="loadFile?filename=test.txt&path="+escape("C:/test.txt")>Download It!</a>  
  8. </body>  
  9. </html>  
<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类如下:
  1. import java.io.File;  
  2. import java.io.FileInputStream;  
  3. import java.io.IOException;  
  4. import java.io.OutputStream;  
  5. import javax.servlet.ServletException;  
  6. import javax.servlet.http.HttpServlet;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.    
  10. public class LoadFile extends HttpServlet {  
  11.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  12.            throws IOException, ServletException {  
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 {
  1. String filename = request.getParameter("filename");  
       String filename = request.getParameter("filename");
  1.        String path = request.getParameter("path");  
  2.        OutputStream o = response.getOutputStream();  
  3.        byte b[] = new byte[1024];  
  4.        // the file to download.   
  5.        File fileLoad = new File(path);  
  6.        // the dialogbox of download file.   
  7.        response.setHeader("Content-disposition""attachment;filename="  
  8.               + "test.txt");  
  9.        // set the MIME type.   
  10.        response.setContentType("text/html");  
  11.        // get the file length.   
  12.        long fileLength = fileLoad.length();  
  13.        String length = String.valueOf(fileLength);  
  14.        response.setHeader("Content_Length", length);  
  15.        // download the file.   
  16.        FileInputStream in = new FileInputStream(fileLoad);  
  17.        int n = 0;  
  18.        while ((n = in.read(b)) != -1) {  
  19.            o.write(b, 0, n);  
  20.        }  
  21.     }  
  22.    
  23.     public void doPost(HttpServletRequest request, HttpServletResponse response)  throws IOException, ServletException {  
  24.        doGet(request, response);  
  25.     }  
  26. }  
       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);
    }
}
   即OK了。


2. 文件上传
   虽然文件上传和下载都能通过开源组件来实现,但如果要自己实现的话还是费一番功夫的。文件上传一般是通过<form>表单结合<input type="file">来实现的。最后在服务端的Servlet中通过requst获取输入流,然后写到服务器磁盘文件中去。虽然原理清楚了,但是是否就可以直接像下面这样写呢?
  1. test.jsp  
  2. <%@page contentType="text/html;charset=GB2312"%>  
  3. <html>  
  4. <body>  
  5.     选择要上传的文件:<br />  
  6.     <form action="accept.jsp" method="post" enctype="multipart/form-data">  
  7.    <input type="file" name="boy" size="38">  
  8.    <br />  
  9.    <input type="hidden" id="tt" name="t" value="1" />  
  10.    <input type="submit" id="gg" name="g" value="提交" />  
  11. </form>  
  12. </body>  
  13. </html>  
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>
  1.   
</pre><div class="dp-highlighter bg_java"><div class="bar"><div class="tools"><strong>[java]</strong> <a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/feichexia/article/details/7105741#">view plain</a><a target=_blank class="CopyToClipboard" title="copy" href="http://blog.csdn.net/feichexia/article/details/7105741#">copy</a><a target=_blank class="PrintSource" title="print" href="http://blog.csdn.net/feichexia/article/details/7105741#">print</a><a target=_blank class="About" title="?" href="http://blog.csdn.net/feichexia/article/details/7105741#">?</a></div></div><ol class="dp-j"><li class="alt">accept.jsp  </li><li><%<span class="annotation">@page</span> contentType=<span class="string">"text/html;charset=GB2312"</span>%>  </li><li class="alt"><%@ page <span class="keyword">import</span>=<span class="string">"java.io.*"</span>%>  </li><li><HTML>  </li><li class="alt"><BODY>  </li><li><%  </li><li class="alt"><span class="comment">//经测试,说明:ServletInputStream类中的readLine(byte[] b, int off, int len) </span>  </li><li><span class="comment">//其中参数 byte[] b 起缓冲作用,此方法一次读取一行,但如果 byte[] b 定义的大小,比要读取的一行需占用的空间要小,则 </span>  </li><li class="alt"><span class="comment">//该方法只读取 byte[] b 指定的大小;再次读取时会继续接着上次未读完的读取;返回值 :返回实际读取的字节数,当读到文档流的 </span>  </li><li><span class="comment">//最后时返回-1。 </span>  </li><li class="alt"><span class="keyword">try</span>{  </li><li>   ServletInputStream in=request.getInputStream();  </li><li class="alt">   File f=<span class="keyword">new</span> File(<span class="string">"c:\\test"</span>,<span class="string">"a.txt"</span>);  </li><li>   FileOutputStream o=<span class="keyword">new</span> FileOutputStream(f);  </li><li class="alt">  </li><li><span class="comment">//如果byte b[]=设置的值太短的话(假如设置为2),那么在 应用的 上传操作时会有影响,具体表现为无法解析文档路径等相关信息 </span>  </li><li class="alt"><span class="keyword">byte</span> b[]=<span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">2046</span>];  </li><li>   <span class="keyword">int</span> n;  </li><li class="alt">   <span class="keyword">int</span> i = <span class="number">0</span>;  </li><li>   <span class="keyword">while</span>((n=in.readLine(b,<span class="number">0</span>,b.length))!=-<span class="number">1</span>)<span class="comment">//ServletInputStream.readLine方法是逐行读取的。当它读完整个文件,返回-1,一般情况下返回读取的字节数 </span>  </li><li class="alt">   {  </li><li>      i++;  </li><li class="alt">      System.out.println(<span class="string">"------"</span>+i);  </li><li>      o.write(b,<span class="number">0</span>,n);  </li><li class="alt">   }  </li><li>   o.close();  </li><li class="alt">   in.close();  </li><li>}<span class="keyword">catch</span>(IOException e){  </li><li class="alt">   e.printStackTrace();  </li><li>}  </li><li class="alt">out.print(<span class="string">"文件已经上传"</span>);  </li><li>%>  </li><li class="alt"><a href=<span class="string">"c:\\test\\a.txt"</span>>查看结果</a>  </li><li></body>  </li><li class="alt"></HTML>  </li></ol></div><pre style="DISPLAY: none" class="java" name="code">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,内容如下:
  1. -----------------------------7db2611a404a4  
  2. Content-Disposition: form-data; name="boy"filename="C:\Users\xijiang\Desktop\test.txt"  
  3. Content-Type: text/plain  
  4.   
  5. Hello World!  
  6. Hello World!  
  7. Hello World!  
  8. -----------------------------7db2611a404a4  
  9. Content-Disposition: form-data; name="t"  
  10.   
  11. 1  
  12. -----------------------------7db2611a404a4  
  13. Content-Disposition: form-data; name="g"  
  14.   
  15. 提交  
  16. -----------------------------7db2611a404a4--  
-----------------------------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!,还多了其他的表单属性值。观察这个文件的内容格式,可以大概看出,
  1. -----------------------------7db2611a404a4  
-----------------------------7db2611a404a4
  1. 是字段间隔符。  
  是字段间隔符。
  1. <PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">-----------------------------7db2611a404a4--</PRE>  
  2. <PRE></PRE>  
  3. <PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">  是结束符。</PRE><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">  <input type="file">对应的值表示为:</PRE><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code"><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">-----------------------------7db2611a404a4  
  4. Content-Disposition: form-data; name="boy"filename="C:\Users\jxq\Desktop\test.txt"  
  5. Content-Type: text/plain  
  6.   
  7. Hello World!  
  8. Hello World!  
  9. Hello World!</PRE><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">   即第一行是 Content-Disposition、name和客户端上传的文件的目录,第二行是上传的文件类型,第三行是空行,接下来是文件内容。</PRE><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">   而表单提交的其他属性值则是通过 Content-Disposition: from-dat; name=xx 来表示。</PRE><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">   所以为了获取上传的文件的真正内容,我们不能简单地读取从request获得的输入流,必须进一步解析。</PRE>  
  10. <PRE></PRE>  
  11. <PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code"></PRE></PRE>  
  12. <PRE></PRE>  
  13. <PRE></PRE>  
  14. <PRE></PRE>  
<div class="dp-highlighter bg_html"><div class="bar"><div class="tools"><strong>[html]</strong> <a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/feichexia/article/details/7105741#">view plain</a><a target=_blank class="CopyToClipboard" title="copy" href="http://blog.csdn.net/feichexia/article/details/7105741#">copy</a><a target=_blank class="PrintSource" title="print" href="http://blog.csdn.net/feichexia/article/details/7105741#">print</a><a target=_blank class="About" title="?" href="http://blog.csdn.net/feichexia/article/details/7105741#">?</a></div></div><ol class="dp-xml"><li class="alt">-----------------------------7db2611a404a4--  </li></ol></div>-----------------------------7db2611a404a4--
<pre>
  1. 是结束符。  
是结束符。
  1. <input type="file">对应的值表示为:  
<input type="file">对应的值表示为:
  1. <PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">-----------------------------7db2611a404a4  
  2. Content-Disposition: form-data; name="boy"filename="C:\Users\jxq\Desktop\test.txt"  
  3. Content-Type: text/plain  
  4.   
  5. Hello World!  
  6. Hello World!  
  7. Hello World!</PRE><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">   即第一行是 Content-Disposition、name和客户端上传的文件的目录,第二行是上传的文件类型,第三行是空行,接下来是文件内容。</PRE><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">   而表单提交的其他属性值则是通过 Content-Disposition: from-dat; name=xx 来表示。</PRE><PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code">   所以为了获取上传的文件的真正内容,我们不能简单地读取从request获得的输入流,必须进一步解析。</PRE>  
  8. <PRE></PRE>  
  9. <PRE style="BACKGROUND-COLOR: rgb(255,255,255)" class=html name="code"></PRE>  
  1. -----------------------------7db2611a404a4  
  2. Content-Disposition: form-data; name="boy"filename="C:\Users\jxq\Desktop\test.txt"  
  3. Content-Type: text/plain  
  4.   
  5. Hello World!  
  6. Hello World!  
  7. Hello World!  
-----------------------------7db2611a404a4Content-Disposition: form-data; name="boy"; filename="C:\Users\jxq\Desktop\test.txt"Content-Type: text/plainHello World!Hello World!Hello World!
  1. 即第一行是 Content-Disposition、name和客户端上传的文件的目录,第二行是上传的文件类型,第三行是空行,接下来是文件内容。  
即第一行是 Content-Disposition、name和客户端上传的文件的目录,第二行是上传的文件类型,第三行是空行,接下来是文件内容。
  1. 而表单提交的其他属性值则是通过 Content-Disposition: from-dat; name=xx 来表示。  
而表单提交的其他属性值则是通过 Content-Disposition: from-dat; name=xx 来表示。
  1. 所以为了获取上传的文件的真正内容,我们不能简单地读取从request获得的输入流,必须进一步解析。  
所以为了获取上传的文件的真正内容,我们不能简单地读取从request获得的输入流,必须进一步解析。
 
  
  1.   
 
  
 
  
 
  
 
 

参考链接:

http://blog.csdn.net/kanaka10/article/details/6526630

http://zhangjunhd.blog.51cto.com/113473/19631


原博客:http://blog.csdn.net/feichexia/article/details/7105741#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值