1. Requirements: The front desk calls the background download video interface multiple times through multithreading to download a video with a large memory in a short time.
2. Implementation principle:
1. When downloading the video, the front desk will create a temporary file of the total size of the original video, and then start multi-threading. Each thread downloads a video segment, and each downloaded video segment will be filled in the temporary file. Specify the location. So the parameters required by this method are: sliceOffset the position of the sliced video; sliceSize the size of each sliced video.
2. Input stream:
FileInputStream fis = new FileInputStream(file);
fis.skip(sliceOffset);//从指定位置读取字节
InputStream bis = new BufferedInputStream(fis);//输入流
Output stream:
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());//输出流
response.reset();//清除首部空白行
response.setContentType("application/octet-stream");//设置客户端接收的数据类型,这里是 二进制
response.setContentLength(sliceSize);//输出长度
The specific code is as follows:
1. Control layer
@PostMapping(value = "downloadVideoSlice")
public ServerResponse<?> downloadVideoSlice(HttpServletRequest request, HttpServletResponse response) {
Integer stAutoId = Integer.parseInt(request.getParameter("stAutoId"));
Integer iId = Integer.parseInt(request.getParameter("iId"));
Integer sliceOffset = Integer.parseInt(request.getParameter("sliceOffset"));
Integer sliceSize = Integer.parseInt(request.getParameter("sliceSize"));
String path = (String) iImageService.downloadVideoSlice(stAutoId, iId).getData();
// 将文件转化成流输出
FileUtil.getOutputStream(path, response, sliceOffset, sliceSize);
return null;
}
2. Implementation class (involving business, you can ignore this part)
@Override
public ServerResponse<?> downloadVideoSlice(int stAutoId, int iId) {
Tstudy tstudy = tstudyMapper.selectByPrimaryKey((long) stAutoId);
Date stDate = tstudy.getStStartdate();
String stDate_str = DateTimeUtil.dateToStr(stDate, "yyyy-MM-dd HH:mm:ss");
VStorageNodeMethod method = CommonConfigCache.getVStorageNodeMethodByDate(stDate, tstudy.getStHospitalcode(),
StorageNodeType.IMAGE, StorageMethodType.DOWNLOAD, Method.HTTP.getType());
String httpHead = method.getSmnHttpVirtualPath();
String rootPath = method.getSnRootpath();
if (method == null) {
return ServerResponse.createByErrorMessage("查无此图");
}
// 获取图片表
String stDate_str1 = DateTimeUtil.dateToStr(stDate, "yyyyMMdd");
Timagecontrol timagecontrol = CommonConfigCache.getTimagecontrol("US", stDate_str1);
TimageExample timageExample = new TimageExample();
timageExample.createCriteria().andIIdEqualTo((long) iId);
timageExample.setOrderByClause("I_Number");
List<Timage> timages = timageMapper.selectByExampleWithTableName(timagecontrol.getcImagetablename(),
timageExample);
Timage timage = null;
if (CollectionUtils.isNotEmpty(timages) && timages.size() > 0) {
timage = timages.get(0);
}
String serverpath = timage.getiServerpath();
String filePath = rootPath + serverpath.replace("/", "\\");
return ServerResponse.createBySuccess(filePath);
}
3. Tools (focus)
Http ContentTpye comparison table
/**
* 将文件转化成流输出
*
* @param path
* @param response
* @param sliceOffset
* @param sliceSize
*/
public static void getOutputStream(String path, HttpServletResponse response, Integer sliceOffset,
Integer sliceSize) {
File file = new File(path);
try {
FileInputStream fis = new FileInputStream(file);
fis.skip(sliceOffset);//从指定位置读取字节
InputStream bis = new BufferedInputStream(fis);//输入流
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());//输出流
response.reset();//清除首部空白行
response.setContentType("application/octet-stream");//设置客户端接收的数据类型,这里是 二进制
response.setContentLength(sliceSize);//输出长度
// 数据缓冲区
byte[] arr = new byte[1024];
int len;
long count = 0;
// 数据读写
while ((len = bis.read(arr)) != -1) {
// 分三种情况
if (len + count > sliceSize) {
// 1.当读取的时候操作自己该线程的下载总量的时候,需要改变len
len = (int) (sliceSize - count);
toClient.write(arr, 0, len);
// 证明该线程下载任务已经完毕,结束读写操作
break;
} else if (len + count < sliceSize) {
// 2.证明还没有到下载总量,直接将内容写入
toClient.write(arr, 0, len);
// 并且使计数器任务累加
count += arr.length;
} else {
// 3.证明改好到下载总量
toClient.write(arr, 0, len);
// 结束读写
break;
}
}
toClient.close();
bis.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} ```