大事记 --深夜篇
本次深夜,本人来记录一下新知道的,如何在JavaWeb工程中利用浏览器像服务器目录上传与下载文件。
所谓文件上传下载
本质是将文件以I/O流形式进行读写。从A以流形式传输到B,在经过还原,即可实现文件传输。
实现过程如下:
- 选中并提交要上传文件。
- 服务器以流形式接收。
- 写入到对应路径。
主体就是这三步,具体对应代码逻辑如下:
①
//在jsp页面添加表单,并且必须有enctype="multipart/form-data"属性
<form action="saveFile" method="post" enctype="multipart/form-data">
请选择文件:<input type="file" name="fileName" value=""><br>
<input type="submit" name="提交">
</form>
效果图如下
②
第二步可能稍微复杂,但是是比较容易的。
//在对应控制类中,以流形式接收该文件
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> itemList = upload.parseRequest(req);
for(var item : itemList){//加强for循环是为了防止表单一次性有过多文件传输
String realName = item.getName();//注意此处获得的是文件真实文件名,也就是从盘符开始的
String[] name = realName.split("\\\\");//此处四个\是因为\自身本为转义符,再加上split方法的特殊性。有兴趣的伙伴可以自行了解
realName = name[name.length-1];//这才是文件的名称
InputStream inputStream = item.getInputStream();//以流形式接收到文件自身内容
}
至此,第二步完成。不过需要说的特别是前两行代码。其实是用了外部封装的jar包(地址在后边)。毕竟站在巨人肩膀才能看的更远。其中的逻辑较为复杂,作者自身还是有点恍惚,就不做解释了。
③
这一步其实有两种实现方法 先来简单的,有兴趣的伙伴可以看看第二种原理。
item.write(new File("D://test/"+realFileName));//在上一个for循环中加入这一行就成功了,当然路径自选。
底层原理不外乎就是
OutputStream outputStream = new FileOutputStream("D://test/"+realFileName);//新建文件输入
byte[] b = new byte[1024];//设定一次性写入大小
int length = inputStream.read(b);//I/O流方式进行读取
while(length!=-1){
outputStream.write(b,0,length);//循环写入
outputStream.flush();
length = inputStream.read(b);
}
这样我们就实现了文件向服务器的传输。经过本人无聊测试后,在局域网内是可以在不同计算机之间传递文件数据的。如果加入公网IP就不得而知了。待本人有需求的话,在来填这个问题的坑吧。
而文件的下载,几乎和上传的原理是相同的。
- 在浏览器发送需要下载的文件名
- 服务器接收并创建输入流读取该文件内容
- 相应对象创建输出流将内容响应回浏览器
第一步这里不再赘述。而第二步比较麻烦的是要相应回浏览器,所以需要设置一些响应的头信息与格式
String fileName = request.getParameter("fileName");//首先get到文件名
InputStream inputStream = new FileInputStream("D://test/"+fileName);//在服务器路径下读取该文件
fileName = URLEncoder.encode(fileName,"UTF-8");//处理中文
// 调用静态常量进行拼接字符串
response.setContentType("application/x-msdownload");
response.setHeader("Content-disposition","attachment;filename="+fileName);
将内容响应回浏览器
OutputStream outputStream = response.getOutputStream();
byte[] b = new byte[1024];
int length = inputStream.read(b);
while(length!=-1){
outputStream.write(b,0,length);
outputStream.flush();
length = inputStream.read(b);
}
尽管实现的手段略有不同,但是从思想的层面来说几乎是如出一辙。只是文件的流向不同而已。夜深时分,自己的脑子也不太清楚。记录一下某段时间的“大”事吧,也希望对大家稍有帮助
差点忘了jar包的地址常用的是apache组织提供的一个包
commons-fileupload.jar
commons-io.jar
http://commons.apache.org/ 选择下载fileupload和io