Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用于Spring引导的工具字节服务_Java_Angular_Spring_Spring Boot_Spring Mvc - Fatal编程技术网

Java 用于Spring引导的工具字节服务

Java 用于Spring引导的工具字节服务,java,angular,spring,spring-boot,spring-mvc,Java,Angular,Spring,Spring Boot,Spring Mvc,我想使用SpringBootRESTAPI在Angular中实现视频播放器。我可以播放视频,但我不能进行视频搜索。每次我使用Chrome或Edge时,视频都会一次又一次地启动 我尝试了这个端点: @RequestMapping(value = "/play_video/{video_id}", method = RequestMethod.GET) @ResponseBody public ResponseEntity<byte[]> getPreview

我想使用SpringBootRESTAPI在Angular中实现视频播放器。我可以播放视频,但我不能进行视频搜索。每次我使用Chrome或Edge时,视频都会一次又一次地启动

我尝试了这个端点:

@RequestMapping(value = "/play_video/{video_id}", method = RequestMethod.GET)
    @ResponseBody public ResponseEntity<byte[]> getPreview1(@PathVariable("video_id") String video_id, HttpServletResponse response) {
        ResponseEntity<byte[]> result = null;
        try {
            String file = "/opt/videos/" + video_id + ".mp4";
            Path path = Paths.get(file);
            byte[] image = Files.readAllBytes(path);

            response.setStatus(HttpStatus.OK.value());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentLength(image.length);
            result = new ResponseEntity<byte[]>(image, headers, HttpStatus.OK);
        } catch (java.nio.file.NoSuchFileException e) {
            response.setStatus(HttpStatus.NOT_FOUND.value());
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        }
        return result;
    }
@RequestMapping(value=“/play\u video/{video\u id}”,method=RequestMethod.GET)
@ResponseBody public ResponseEntity getPreview1(@PathVariable(“video_id”)字符串video_id,HttpServletResponse){
ResponseEntity结果=空;
试一试{
字符串文件=“/opt/videos/”+video_id+”.mp4”;
Path Path=Path.get(文件);
byte[]image=Files.readAllBytes(路径);
response.setStatus(HttpStatus.OK.value());
HttpHeaders=新的HttpHeaders();
headers.setContentType(MediaType.APPLICATION\u OCTET\u STREAM);
headers.setContentLength(image.length);
结果=新响应性(图像、标题、HttpStatus.OK);
}catch(java.nio.file.NoSuchFileException){
response.setStatus(HttpStatus.NOT_FOUND.value());
}捕获(例外e){
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
返回结果;
}
我发现这篇文章提供了一些IDE:

但目前它不起作用。当我尝试移动位置时,视频从一开始就再次播放

我使用这个播放器:

我已将其配置为:

<div class="media">
        <div
          class="class-video mr-3 mb-1"
          plyr
          [plyrPlaysInline]="true"
          [plyrSources]="gymClass.video"
          (plyrInit)="player = $event"
          (plyrPlay)="played($event)">
        </div>
        <div class="media-body">
          {{ gymClass.description }}
        </div>
      </div>

{{gymClass.description}}
您知道如何解决此问题吗?

第一种解决方案:使用
FileSystemResource
FileSystemResource在内部处理字节范围标头支持,读取和写入适当的标头

这种方法有两个问题

  • 它在内部使用
    FileInputStream
    读取文件。这适用于小文件,但不适用于通过字节范围请求提供服务的大文件
    FileInputStream
    将从头开始读取文件,并丢弃不需要的内容,直到它重新记录请求的开始偏移量。这可能会导致较大文件的速度减慢

  • 它将
    “application/json”
    设置为
    “Content Type”
    响应头。因此,我提供了自己的
    “内容类型”
    标题

  • 第三种解决方案:也使用
    RandomAccessFile
    ,但是
    StreamingResponseBody
    而不是
    HttpServletResponse
    以及html:

    <div
      #plyr
      plyr
      [plyrPlaysInline]="false"
      [plyrSources]="videoSources"
    ></div>
    
    
    
    
    如果您在Chrome中使用
    元素,则仅当端点通过以a表示满足请求并以响应进行响应来实现部分内容请求时,seeking才起作用。

    角度代码是什么样子的?帖子已更新。我已更新我的答案。我检查过了,所有三个java控制器都在工作,我也可以跳过视频。如果我们有数百个客户端,哪一个解决方案会消耗更少的资源?2。或3。您还可以查看spring。springreactive允许您以异步方式处理函数执行。这种方法适用于
    异步文件通道
    ,它使用本机函数
    读取文件(长句柄、长地址、整数、长偏移量、长重叠)
    。这里的偏移量是正在读取的文件中的位置。
    FileInputStream
    的情况并非如此,它使用的是
    readBytes(byte b[],int off,int len)
    ,其中偏移量是目标缓冲区中的位置。在azure core中,已经实现了桥接电抗器(spring reactive使用的反应库)和
    异步文件通道
    。如果你想这样做,你可以在这里找到我使用这个播放器的文档:
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.RandomAccessFile;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    public class Stream {
        @GetMapping(value = "/play_video/{video_id}")
        @ResponseBody
        public void stream(        
                @PathVariable("video_id") String video_id,
                @RequestHeader(value = "Range", required = false) String rangeHeader,
                HttpServletResponse response) {
    
            try {
                OutputStream os = response.getOutputStream();
                long rangeStart = 0;
                long rangeEnd;
                String filePathString = "/opt/videos/" + video_id + ".mp4";
                Path filePath = Paths.get(filePathString);
                Long fileSize = Files.size(filePath);
                byte[] buffer = new byte[1024];
                RandomAccessFile file = new RandomAccessFile(filePathString, "r");
                try (file) {
                    if (rangeHeader == null) {
                        response.setHeader("Content-Type", "video/mp4");
                        response.setHeader("Content-Length", fileSize.toString());
                        response.setStatus(HttpStatus.OK.value());
                        long pos = rangeStart;
                        file.seek(pos);
                        while (pos < fileSize - 1) {                        
                            file.read(buffer);
                            os.write(buffer);
                            pos += buffer.length;
                        }
                        os.flush();
                        return;
                    }
    
                    String[] ranges = rangeHeader.split("-");
                    rangeStart = Long.parseLong(ranges[0].substring(6));
                    if (ranges.length > 1) {
                        rangeEnd = Long.parseLong(ranges[1]);
                    } else {
                        rangeEnd = fileSize - 1;
                    }
                    if (fileSize < rangeEnd) {
                        rangeEnd = fileSize - 1;
                    }
    
                    String contentLength = String.valueOf((rangeEnd - rangeStart) + 1);
                    response.setHeader("Content-Type", "video/mp4");
                    response.setHeader("Content-Length", contentLength);
                    response.setHeader("Accept-Ranges", "bytes");
                    response.setHeader("Content-Range", "bytes" + " " + rangeStart + "-" + rangeEnd + "/" + fileSize);
                    response.setStatus(HttpStatus.PARTIAL_CONTENT.value());
                    long pos = rangeStart;
                    file.seek(pos);
                    while (pos < rangeEnd) {                    
                        file.read(buffer);
                        os.write(buffer);
                        pos += buffer.length;
                    }
                    os.flush();
    
                }
    
            } catch (FileNotFoundException e) {
                response.setStatus(HttpStatus.NOT_FOUND.value());
            } catch (IOException e) {
                response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            }
    
        }
    
    }
    
    
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
    
    @Controller
    public class Stream2 {
        @GetMapping(value = "/play_video/{video_id}")
        @ResponseBody
        public ResponseEntity<StreamingResponseBody> stream(
                @PathVariable("video_id") String video_id,
                @RequestHeader(value = "Range", required = false) String rangeHeader) {        
            try {
                StreamingResponseBody responseStream;
                String filePathString = "/opt/videos/" + video_id + ".mp4";
                Path filePath = Paths.get(filePathString);
                Long fileSize = Files.size(filePath);
                byte[] buffer = new byte[1024];      
                final HttpHeaders responseHeaders = new HttpHeaders();
    
                if (rangeHeader == null) {
                    responseHeaders.add("Content-Type", "video/mp4");
                    responseHeaders.add("Content-Length", fileSize.toString());
                    responseStream = os -> {
                        RandomAccessFile file = new RandomAccessFile(filePathString, "r");
                        try (file) {
                            long pos = 0;
                            file.seek(pos);
                            while (pos < fileSize - 1) {                            
                                file.read(buffer);
                                os.write(buffer);
                                pos += buffer.length;
                            }
                            os.flush();
                        } catch (Exception e) {}
                    };
                    return new ResponseEntity<>(responseStream, responseHeaders, HttpStatus.OK);
                }
    
                String[] ranges = rangeHeader.split("-");
                Long rangeStart = Long.parseLong(ranges[0].substring(6));
                Long rangeEnd;
                if (ranges.length > 1) {
                    rangeEnd = Long.parseLong(ranges[1]);
                } else {
                    rangeEnd = fileSize - 1;
                }
                if (fileSize < rangeEnd) {
                    rangeEnd = fileSize - 1;
                }
    
                String contentLength = String.valueOf((rangeEnd - rangeStart) + 1);
                responseHeaders.add("Content-Type", "video/mp4");
                responseHeaders.add("Content-Length", contentLength);
                responseHeaders.add("Accept-Ranges", "bytes");
                responseHeaders.add("Content-Range", "bytes" + " " + rangeStart + "-" + rangeEnd + "/" + fileSize);
                final Long _rangeEnd = rangeEnd;
                responseStream = os -> {
                    RandomAccessFile file = new RandomAccessFile(filePathString, "r");
                    try (file) {
                        long pos = rangeStart;
                        file.seek(pos);
                        while (pos < _rangeEnd) {                        
                            file.read(buffer);
                            os.write(buffer);
                            pos += buffer.length;
                        }
                        os.flush();
                    } catch (Exception e) {}
                };
                return new ResponseEntity<>(responseStream, responseHeaders, HttpStatus.PARTIAL_CONTENT);
    
            } catch (FileNotFoundException e) {
                return new ResponseEntity<>(HttpStatus.NOT_FOUND);
            } catch (IOException e) {
                return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
            }
        }
    }
    
    
    export class AppComponent implements OnInit {
      videoSources: Plyr.Source[];
      ngOnInit(): void {
        const fileName = 'sample';
        this.playVideoFile(fileName);
      }
    
      playVideoFile(fileName: string) {
        this.videoSources = [
          {
            src: `http://localhost:8080/play_video/${fileName}`,
          },
        ];
      }
    }
    
    
    <div
      #plyr
      plyr
      [plyrPlaysInline]="false"
      [plyrSources]="videoSources"
    ></div>