说说Web开发之远程与本地文件下载的细节

    我想在开发Web项目的过程中,免不了的功能,应该就是上传和下载了吧。虽然这个功能很常见,但是我想,遇到坑的也不是一两个了吧。所以,就用这篇文章来写一写,在这开发中的问题。

    关于上传的问题,这个还算好解决,没有什么大问题,在上传的时候,路径的话,可以选择为本地路径,或者为服务器的路径,如果是公司开发项目的话,这个肯定是放在服务器的某个目录下面的,或者放在存储云上(比如,七牛云存储,这个个人还是觉得比较好的),所以,上传的问题不是很多,而且在我的另外的文章中,对这个已经进行了几种方法的代码演示,所以这里就不进行过多描述了,如果不是很明白的,可以看看另外一篇文章“手把手教你玩转SpringMvc”。。。

   咳咳,好了,进入本篇文章的正题了。关于下载文件的话,也同样有两种,一种就是下载本地的路径上的文件。比如:”C:\helloworld.pdf“,另外一种就是从远程服务器进行下载对应url的文件,就比如http://p09v5ioet.bkt.clouddn.com/797ec79c-56c2-4d7d-98d9-aeaa705fd336.pdf,其实就是网络资源。。好了,重点来了,发现两种路径有啥最大的不同了吗?是的,如果是本地的话,那么其实运用下载的时候使用的就是file协议,而当进行的是网络资源的时候,那么就会出现http,或者https这类似的协议(这两种用得是最多的)。所以,协议都不一样,那么通过不同的方法,肯定实现的方法也就会有差别了。下面的话,就介绍针对不同的情况,来进行文件的下载。

第一种:下载本地路径的文件

    如果想实现的是这种情况的文件下载的话,可以采取最初的servlet的文件流下载的代码,这个不是很难,可以直接百度就可以明白。这里,说一下,如何基于SpringMVC框架的一种很清晰,明了的一种写法。

@ResponseBody
@RequestMapping(value = "/downloadcontract")	
public ResponseEntity<byte[]> downLoadCurrentContract(Long id , String fileUrl , HttpServletRequest request, 

HttpServletResponse response) throws  Exception {
//这种方法只能读本地的文件,切记切记切记
			try {
			File file=new File(fileUrl);
			HttpHeaders headers = new HttpHeaders();
			String fileName = "合同文件.doc";
			fileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");//为了解决中文名称乱码问题
			headers.setContentDispositionFormData("attachment", fileName);
			headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
				return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
						headers, HttpStatus.CREATED);
			} catch (Exception e) {
				e.printStackTrace();
				//throw  new RuntimeException("文件流内容读取错误");
			}
			return null;
这种方法是不是很简单呢?但是。请特别的记住一下,如果用这样的方式去请求下载一个网络资源的url的文件的话,那么在使用这个方法的时候,就会报一个”文件路径无法不存在“的错误,但是呢,直接在浏览器通过url进行访问的话,就会直接下载了对应的文件,这是为什么呢?其实,很简单,这是由于这种方法,它只能够进行本地文件的下载。所以,使用的时候注意一下就好了。

第二种:远程文件下载

直接上代码吧。远程的含义就不多说了,就是网络资源路径。。。。。。。。。

方法一:

@ResponseBody
	@RequestMapping(value = "/downloadcontract")
	public void downLoadCurrentContract(Long id , String fileUrl , HttpServletRequest request, HttpServletResponse response) throws  Exception {
int pointIndex = fileUrl.lastIndexOf(".");
		BufferedInputStream bis ;
		//如果有找到符号".",
		if(pointIndex != -1) {
			String fileName = "合同文件" + fileUrl.substring(pointIndex, fileUrl.length());
			URL url = new URL(fileUrl);
			URLConnection conn = url.openConnection();
			int filesize = conn.getContentLength(); // 取数据长度
			bis = new BufferedInputStream(conn.getInputStream());
			// 清空response
			response.reset();
			// 文件名称转换编码格式为utf-8,保证不出现乱码,这个文件名称用于浏览器的下载框中自动显示的文件名
			response.addHeader("Content-Disposition",
					"attachment;filename=" + new String(fileName.getBytes("utf-8"), "iso8859-1"));
			response.addHeader("Content-Length", "" + filesize);
			BufferedOutputStream os = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream");
			// 从输入流中读入字节流,然后写到文件中
			byte[] buffer = new byte[1024];
			int nRead;
			while ((nRead = bis.read(buffer, 0, 1024)) > 0) { // bis为网络输入流
				os.write(buffer, 0, nRead);
			}
			bis.close();
			os.flush();
			os.close();
		}
大家可以看到,这种方法就能够实现远程文件的下载了,其实就是用的原生的Java网络编程中的URLConnection对象来进行的,之前在学习的时候确实没怎么关注,只是单纯的知道这么个对象,现在回头看看,这才是靠近底层的内容,其他的框架封装的下载方法,很多都是基于这样的一种方法的。

另外,通过这种方法的话,默认下载的地方就是浏览器下载内容的保存地方,而且如果使用的是谷歌浏览器的话,是不会弹出一个对话框的,这是谷歌浏览器默认情况;如果是使用的火狐浏览器的话,那么就会弹出一个对话框来提示用户是否确认进行下载,还是下载完成后直接打开的选择。这是一个需要区分的地方。。

咳咳,还有,就是可能会碰到一个需求就是说,默认将下载的内容,放在一个地方,这样的话,就方便以后对下载文件内容的管理,比如就是想放在”C盘”,那么还可以利用下面的方法进行,其实类似上面的方法,只是提供给需要的人看看好了。

@ResponseBody
@RequestMapping(value = "/downloadcontract")	
public void downLoadCurrentContract(Long id , String fileUrl , HttpServletRequest request, 

URL theURL = new URL(fileUrl);
		String filePath = "C:\\";
		URLConnection con = theURL.openConnection();
		String urlPath = con.getURL().getFile();
		String fileFullName = "合同.doc";
		if(fileFullName !=null){
			byte[] buffer = new byte[4*1024];
			int read;
			String path = filePath + "/" +fileFullName;
			File fileFolder = new File(filePath);
			if(!fileFolder.exists()){
				fileFolder.mkdirs();
			}
			InputStream in = con.getInputStream();
			FileOutputStream os = new FileOutputStream(path);
			while((read = in.read(buffer)) > 0){
				os.write(buffer, 0, read);
			}
			os.close();
			in.close();
		}
}

三:网络编程的一些知识点

(1)首先说一下关于网络的两种协议,TCP与UDP

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值