【前后端实现文件下载或浏览】

文章介绍了如何在前端使用JavaScript通过window.open打开URL来触发文件下载或浏览,以及后端Java如何通过HttpServletResponse返回文件流,支持附件下载和在线浏览。关键在于处理字节流和设置Content-Disposition头,以控制文件是以附件下载还是在线显示。此外,讨论了IO流的分类,包括字符流和字节流,并提供了字节流读写文件的示例代码。
摘要由CSDN通过智能技术生成

背景

前端html\js\css,使用a标签或者iframe,笔者使用window.open(url)—重新打开标签页地址栏显示的接口路径;后端返回客户端[HttpServletResponse] 文件流(以附件的方式[attachment]下载,或者在线方式[inline]浏览)。
笔者编译平台为x5,因此调用.j文件才可以使用 HttpServletResponse

前端

var getFileStream = function(subPath, ywlx, operateType) {
		console.log("the URL of dzzzRow: "+ subPath);
		if (!subPath) return;
				var realFileName = subPath.substr(subPath.lastIndexOf("/")+1);
				// 提交前需要进行URL转换,在URL上补足bsessionid等必要信息
				var url = require.toUrl("$UI/sybdc/service/simpleFileStore.j?bsessionid=" + this.getContext().getBSessionID());
				// 用get方式传参
				url = url 
					+ "&subPath=" + subPath 
					+ "&realFileName=" + realFileName
					+ (ywlx? "&ywlx="+ywlx:"")
					+ (operateType? "&operateType="+ operateType:"");
				window.open(url);
	}


// 调用方式:浏览
this.getFileStream(row.val("URL"), "dzzz");
// 调用方式:下载
this.getFileStream(row.val("URL"), "dzzz", "download");

后端java

当ywlx = “dzzz”时,前端传入的路径若文件不存在则会抛异常,读者可根据自己的业务需求另作处理(若文件不存在重新生成文件或者返回前端文件不存在);注意:这里下载与浏览使用的get方式调接口;new File对象并未与磁盘交互,而是在使用File对象的函数(file.exist()、getPath()等等)时才读写磁盘;这里使用的字节文件流

/**
	 * get为获取文件 浏览或者下载
	 **/
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String operateType = request.getParameter("operateType");
		if ("copy".equals(operateType)) {
			copyFile(request, response);
		} else {
			getFile(request, response);
		}
	}
	
	
	private static final int BUFFER_SIZE = 32768 * 8;

	private static void getFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String ownerID = request.getParameter("ownerID"); //对应的是表 WW_SLCLB 中的主键clid
		String realFileName = URLEncoder.encode(request.getParameter("realFileName"), "utf-8");
		String storeFileName = request.getParameter("storeFileName");
		String operateType = request.getParameter("operateType");
		String subPath = request.getParameter("subPath");
		String ywlx = request.getParameter("ywlx");
		/* String fileSize = request.getParameter("fileSize"); */
		File file = null;
		if ("dzzz".equals(ywlx)) {
//			D:/wwdzzz/sy_gtj   /   2023/6/9/CA50808B97900001CBFC12D84B54AC00/苏(2016)射阳县不动产权第0003129号.pdf
			file = new File(dzzzDownloadPath + File.separator + subPath);
		} else {
			file = new File(docStorePath + (subPath != null ? subPath : "") + File.separator + ownerID + File.separator + storeFileName);
		}
		if(!file.exists()){
			System.out.println(subPath + "--------文件不存在----------");
		}
		
		FileInputStream fis = new FileInputStream(file);
		response.setHeader("Cache-Control", "pre-check=0, post-check=0, max-age=0");

		String fileNameKey = "filename";

		if ("download".equals(operateType)) { // 以附件方式下载
			response.addHeader("Content-Disposition", "attachment; " + fileNameKey + "=\"" + realFileName + "\"");
		} else { // 以在线方式浏览
			response.addHeader("Content-Disposition", "inline; " + fileNameKey + "=\"" + realFileName + "\"");
		}

		OutputStream os = response.getOutputStream();
		byte[] buffer = new byte[BUFFER_SIZE];
		try {
			int read;
			while ((read = fis.read(buffer)) != -1) {
				os.write(buffer, 0, read);
			}
		} finally {
			fis.close();
		}
	}

其他

关键点在于文件流的读写,即输入流输出流;

IO流分两种;字符流&字节流

1、什么是流
流是个抽象的概念,是对输入输出设备的抽象,输入流可以看作一个输入通道,输出流可以看作一个输出通道。流是单向的
输入流是相对程序而言的,外部传入数据给程序需要借助输入流。输入流是用于读取数据,InputStream 抽象类,定义输入流的读取字节方法,所有的输入流都继承自此类。
输出流是相对程序而言的,程序把数据传输到外部需要借助输出流。输出流用于写数据,OutputStream是所有输出流的父类,也是抽象类。
流分为节点流和处理流,节点流是低级流,负责读写数据的流。
处理流式高级流,不能独立存在,用于处理其他的流。主要是为了简化读写数据中的操作。
2、字节流与字符流
字节流是由字节组成的,字符流是由字符组成的
网络传输的都是二级制数据,字符流又不是二级制,那么不论对方是怎么处理的文件,他最终传给我的一定是字节流

在这里插入图片描述

直接使用字节流保存

// 获取一个浏览器
DefaultHttpClient httpclient = new DefaultHttpClient();
// 获取get请求
HttpGet httpget = new HttpGet(url);
// 请求对方服务器
HttpResponse response = httpclient.execute(httpget);
// 获取返回数据
InputStream inputStream = response.getEntity().getContent();

// new 一个本地文件
            File file = new File("D:\\11111.pdf");
            // 创建相对于程序的输出流
            OutputStream outputStream = null;
            try {
                outputStream = new FileOutputStream(file);
                // 读取数据
                byte[] b = new byte[1024];// b - 数据
                int off = 0;// off - 数据中的起始偏移量。
                int len = -1;// len - 要写入的字节数。
                while ((len = inputStream.read(b)) != -1) {// 从输入流读取一些字节数,并将它们存储到缓冲区b。实际读取的字节数作为整数返回,如果没有字节可用,因为流在文件末尾,则返回值-1;否则,读取至少一个字节并存储到b。
                    outputStream.write(b, off, len);// 数组b中的一些字节按顺序写入输出流; 元素off是写入的第一个字节,len是此操作写入的最后一个字节。
                }
                outputStream.flush();// 刷新此输出流并强制任何缓冲的输出字节被写出。
            } catch (IOException e) {
                System.out.println("异常");
                e.printStackTrace();
            } finally {
                inputStream.close();//关闭此输入流并释放与此流相关联的任何系统资源。
                outputStream.close();//关闭此输出流并释放与此流相关联的任何系统资源。
            }

使用字符流或者其他子类详情参考:
链接: 接口返回流并保存本地
java IO选择流的原则及其与IO流相关类的关系
JAVA基础知识之BufferedReader流

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值