RandomAccessFile类是随机读取文件类可以支持读和写,还可以冲指定位置开始读,从我在网上查到的资料来看,RandomAccessFile一般是用于视频播放的实现,
一般来说,前端在播放视频时请求头会携带range这个参数,这个参数记录了,当前播放到了哪一个字节
如下所示:
所以我们可以通过request来拿取这个数据然后字符串切割得到要播放的具体位置
然后response要返回两个东西,一是响应状态码206,表示只是上传部分请求
还有一个是响应体 Content-Rang 意思是,确立起始位置,终止位置以及整个视频所需字节长度
格式例如 Content-Range: bytes 0-169704/169705
range是播放到的具体位置,fileLength是这个文件的长度
response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength);
@GetMapping("/play")
public void play( String Md5, String fileName,HttpServletRequest request, HttpServletResponse response) throws IOException{
File file = new File(PATH + Md5 + "\\" + fileName);
long fileLength = file.length();
// 随机读文件
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
//获取从那个字节开始读取文件
String rangeString = request.getHeader("Range");
//拿取range
long range = Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));
//获取响应的输出流
OutputStream outputStream = response.getOutputStream();
//设置内容类型(注释也可以)
response.setHeader("Content-Type", "video/mp4");
//返回码需要为206,代表只处理了部分请求,响应了部分数据(必须)
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
// 移动访问指针到指定位置
randomAccessFile.seek(range);
// 每次请求只返回1MB的视频流
byte[] bytes = new byte[1024 * 1024];
int len = randomAccessFile.read(bytes);
//设置此次相应返回的数据长度(注释也可以)
response.setContentLength(len);
//设置此次相应返回的数据范围(必须,和返回状态码206相对应)
response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength);
// System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.");
// System.out.println("bytes "+range+"-"+(fileLength-1)+"/"+fileLength);
// 将这1MB的视频流响应给客户端
outputStream.write(bytes, 0, len);
outputStream.close();
randomAccessFile.close();
}
我是根据文件md5和名字存文件的,这里可以忽略,
应该是只能用RandomAccessFile来读分片读文件,如果我用InputStream就只能读取整个文件了,这样子视频就不能拖动进度条了,因为inputstrem不能指定要读取的位置
这是用inputstrem来读取
@GetMapping("/preview")
public void preview(String Md5, String fileName,HttpServletResponse response) throws IOException {
File file = new File(PATH + Md5 + "\\" + fileName);
String filename = file.getName();
byte[] bytesArray = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(bytesArray);
fis.close();
OutputStream os = response.getOutputStream();
os.write(bytesArray);
//attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
// filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
os.close();
}