|
@@ -12,8 +12,13 @@ import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
import javax.servlet.ServletRequest;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.File;
|
|
|
import java.io.IOException;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.io.RandomAccessFile;
|
|
|
import java.net.URLEncoder;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Paths;
|
|
|
import java.util.Map;
|
|
|
|
|
|
/**
|
|
@@ -41,8 +46,9 @@ public class ServletUtils {
|
|
|
* @param response 响应
|
|
|
* @param filename 文件名
|
|
|
* @param content 附件内容
|
|
|
+ * @param request
|
|
|
*/
|
|
|
- public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
|
|
|
+ public static void writeAttachment(HttpServletResponse response, String filename, byte[] content, HttpServletRequest request) throws IOException {
|
|
|
// 设置 header 和 contentType
|
|
|
if (filename.contains("mp4")) {
|
|
|
response.setHeader("Content-Disposition", "inline");
|
|
@@ -58,6 +64,108 @@ public class ServletUtils {
|
|
|
IoUtil.write(response.getOutputStream(), false, content);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 为了适配ios能够视频浏览,在文件溜获取的位置加上一些头部信息
|
|
|
+ * @param content 内容
|
|
|
+ * @param reqRange range
|
|
|
+ * @param response 响应体
|
|
|
+ */
|
|
|
+ public static void transfer(byte[] content, String reqRange, HttpServletResponse response){
|
|
|
+ try {
|
|
|
+ File sf = fileTransition(content);
|
|
|
+ RspInfo ri= getPartFileRsp( sf, reqRange) ;
|
|
|
+ response.setContentLength((int)ri.content_Length);
|
|
|
+ response.setHeader("Content-Range", ri.content_Range);
|
|
|
+ response.setHeader("Accept-Ranges", "bytes");
|
|
|
+ response.setHeader("Content-Disposition", "inline");
|
|
|
+ response.setContentType("video/mp4");
|
|
|
+ response.setHeader("Access-Control-Allow-Origin","*");
|
|
|
+ response.setHeader("Cache-Control","no-cache");
|
|
|
+ response.setStatus(206);
|
|
|
+ sendToClient(ri, response.getOutputStream(), sf);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public static RspInfo getPartFileRsp(File sf,String reqRange) throws Exception {
|
|
|
+ RspInfo rinfo = new RspInfo();
|
|
|
+
|
|
|
+/* 1、Range 类型 1)bytes=x...- 2)bytes=x...-x... //Range:(unit=first byte pos)-[last byte pos]
|
|
|
+如:Range: bytes=0- Range: bytes=0-801
|
|
|
+
|
|
|
+2、对应 Content-Range: bytes x...(开始读取位置)-y...(读取结束位置)/z...(文件总大小) //Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]
|
|
|
+如:Content-Range: bytes 0-800/801 //801:文件总大小
|
|
|
+*/
|
|
|
+ if(null!=reqRange){
|
|
|
+ String[] ranplits= reqRange.split("=");
|
|
|
+ if(ranplits.length!=2)throw new Exception("range format wrong ");
|
|
|
+ String lenstr=ranplits[1];
|
|
|
+ String[] flens=lenstr.split("-",-1);
|
|
|
+ if(flens.length!=2)throw new Exception("rangelen format wrong ");
|
|
|
+ long fpos =Long.valueOf(flens[0]);
|
|
|
+ long lpos= flens[1].length()>0?Long.valueOf(flens[1]):sf.length()-1; //表示文件读取文件大小
|
|
|
+
|
|
|
+ rinfo.skipLenth=fpos;
|
|
|
+ rinfo.content_Length=lpos-fpos+1;
|
|
|
+ rinfo.content_Range=ranplits[0]+" "+fpos+"-"+lpos+"/"+sf.length();
|
|
|
+ }
|
|
|
+ return rinfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void sendToClient(RspInfo rinfo , OutputStream os, File sf) {
|
|
|
+
|
|
|
+ RandomAccessFile raf;
|
|
|
+ try {
|
|
|
+ raf = new RandomAccessFile(sf, "r");
|
|
|
+ byte[] b=new byte[102400];
|
|
|
+ raf.seek(rinfo.skipLenth);
|
|
|
+ long readlen=rinfo.content_Length; //需要读取的字节长度
|
|
|
+ int clen=0;
|
|
|
+ while(readlen>0&&(clen=raf.read(b))!=-1){
|
|
|
+ if(readlen>clen){
|
|
|
+ os.write(b,0,clen);
|
|
|
+ }else{
|
|
|
+ os.write(b,0, (int)readlen);
|
|
|
+ }
|
|
|
+ readlen-=clen;
|
|
|
+ }
|
|
|
+ raf.close();
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }finally{
|
|
|
+ if(os!=null){
|
|
|
+ try {
|
|
|
+ os.flush();
|
|
|
+ os.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将bute写入文件
|
|
|
+ * @param content 内容字节
|
|
|
+ * @return file
|
|
|
+ * @throws IOException 异常
|
|
|
+ */
|
|
|
+ public static File fileTransition(byte[] content) throws IOException{
|
|
|
+ File file = new File("data/file/videoTest.mp4");
|
|
|
+ if(!file.exists()){
|
|
|
+ file.mkdir();
|
|
|
+ }
|
|
|
+ Files.write(Paths.get("data/file/videoTest.mp4"), content);
|
|
|
+ return file;
|
|
|
+ }
|
|
|
+
|
|
|
+ static class RspInfo{
|
|
|
+ public long content_Length=-1;
|
|
|
+ public String content_Range="";
|
|
|
+ public long skipLenth=-1;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @param request 请求
|
|
|
* @return ua
|