近期在存储服务。遇到了一个棘手的问题,电脑端,包括了Android的浏览器,应用都能正常的播放上传的mp4应用,但是链接一到苹果上就有问题了。
搜了网上很快发现了问题。是因为苹果的要求很奇葩。
苹果会发两次请求,第一次请求是不带Range的,这一波是只能返回Content-Length的,不能返回Content-Range以及其他的。
第二波是需要根据苹果的请求的Range来返回Range的内的数据,然后状态码要设置为206,才不会出问题。
另外。在ContentType上也有问题,就是如果你的mp4的Content-Type设置为video/mpeg4 也是不行的,也只能是video/mp4才可以访问。
重点已经讲完,下面是研究完成粗写的代码。部分方法你们是没有的,请不要照抄,请根据修改。
代码语言:javascript复制 public void readAndFlush(String fileContentType,File file,HttpServletResponse response,String fileId,boolean needCache,String fileName,String range) throws UploadException{
int statusCode = 200;
try {
response.addHeader("Content-Type",fileContentType);
response.addHeader("Cache-Control","max-age=259200");
String fileType = FileUtils.getFileType(fileName);
if (fileType.equals(FileConstant.TYPE_VEDIO)){
response.setHeader("content-disposition", "inline");
}else if (fileType.equals(FileConstant.TYPE_IMAGE)){
response.setHeader("content-disposition", "inline");
}else {
response.setHeader("content-disposition", "attachment;filename=" URLEncoder.encode(fileName, "UTF-8"));
}
InputStream inputStream = new FileInputStream(file);
//开始处理ContentRange
long startByte = 0;
long endByte = (inputStream.available() - 1);
long contentLength = endByte - startByte 1;
if (range != null && range.contains("bytes") && range.contains("-")){
statusCode = 206;
range = range.substring(range.lastIndexOf("=") 1).trim();
String ranges[] = range.split("-");
try {
//根据range解析下载分片的位置区间
if (ranges.length == 1) {
//情况1,如:bytes=-1024 从开始字节到第1024个字节的数据
if (range.startsWith("-")) {
endByte = Long.parseLong(ranges[0]);
}
//情况2,如:bytes=1024- 第1024个字节到最后字节的数据
else if (range.endsWith("-")) {
startByte = Long.parseLong(ranges[0]);
}
}
//情况3,如:bytes=1024-2048 第1024个字节到2048个字节的数据
else if (ranges.length == 2) {
startByte = Long.parseLong(ranges[0]);
endByte = Long.parseLong(ranges[1]);
}
} catch (NumberFormatException e) {
startByte = 0;
endByte = (inputStream.available() - 1);
}
contentLength = endByte - startByte 1;
response.setHeader("Content-Length",String.valueOf(contentLength));
}
// 处理请求的Range完成,开始进行字节流操作。
BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
long startRange = startByte;
long endRange = endByte;
if (range == null){
startRange = 0;
endRange = 1;
}
response.setHeader("Content-Range","bytes " startRange "-" endRange "/" String.valueOf(inputStream.available()));
// 开始进行传输大小的操作
long transmitted = 0;
byte[] buff = new byte[2048];
int len = 0;
while ((transmitted len) <= contentLength && (len = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, len);
transmitted = len;
}
//处理不足buff.length部分
if (transmitted < contentLength) {
len = inputStream.read(buff, 0, (int) (contentLength - transmitted));
outputStream.write(buff, 0, len);
transmitted = len;
}
// IOUtils.copy(inputStream,response.getOutputStream());
response.setStatus(statusCode);
outputStream.flush();
response.flushBuffer();
if (needCache){
cacheService.cacheToRedis(fileId);
}
}catch (Exception e){
logger.info("读取数据并返回时失败,文件id为:" fileId ",文件类型为:" fileContentType,e);
e.printStackTrace();
throw new UploadException("读取数据并返回失败");
}
}
未经允许不得转载:RffanLAB|Rffan实验室 » [Spring Boot]Safari(iPhone系浏览器)相关无法播放视频