Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC StreamingResponseBody return chunked file

I run into a problem that using springMVC StreamingResponseBody to return a video. The video I get from server was interrupted. Could you guys give me a hint?

The video file got chunked

enter image description here

My controller:

    @RestController
    @RequestMapping("/rest/videos")
    public class VideoController {
        private String videoLocation = "videos";
        private ConcurrentHashMap<String, File> videos = new ConcurrentHashMap<String, File>();

        @PostConstruct
        public void init() {
            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            File dir = new File(classloader.getResource(videoLocation).getPath());
            System.out.println(dir);
            videos.clear();
            videos.putAll(Arrays.asList(dir.listFiles()).stream()
                    .collect(Collectors.toMap((f) -> {
                        String name = ((File) f).getName();
                        return name;
                    }, (f) -> (File) f)));
        }

        @RequestMapping(method = RequestMethod.GET, value = "/{video:.+}")
        @PreAuthorize("permitAll")
        public StreamingResponseBody stream(@PathVariable String video)
                throws FileNotFoundException {
            File videoFile = videos.get(video);
            final InputStream videoFileStream = new FileInputStream(videoFile);
            return (os) -> {
                readAndWrite(videoFileStream, os);
            };
        }

        @RequestMapping(method = RequestMethod.GET)
        @PreAuthorize("permitAll")
        public Set<String> list() {
            System.out.println(videos.keySet());
            return videos.keySet();
        }

        private void readAndWrite(final InputStream is, OutputStream os)
                throws IOException {
            byte[] data = new byte[2048];
            int read = 0;
            int i = 0;
            while ((read = is.read(data)) > 0) {
                os.write(data, 0, read);
                System.out.println("buffer Number "+i++);
            }
            os.flush();
        }
    }

My configure:

@Configuration
public class AsyncWebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        System.out.println("My AsyncSupportConfigurer!");
        configurer.setDefaultTimeout(-1);
        configurer.setTaskExecutor(asyncTaskExecutor());
    }

    @Bean
    public AsyncTaskExecutor asyncTaskExecutor() {
        System.out.println("My AsyncSupportConfigurer!!~");
        return new SimpleAsyncTaskExecutor("async");
    }
}

My web.xml

       <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/business-config.xml</param-value>
        </context-param>

        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

        <servlet>
            <servlet-name>mvc-dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <async-supported>true</async-supported>
        </servlet>

        <servlet-mapping>
            <servlet-name>mvc-dispatcher</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>

my dispatcher servlet

    <context:component-scan base-package="com.BackEnd.restful.mvc"/>

    <mvc:resources mapping="/app/**" location="/app/build/"/>

    <mvc:annotation-driven/>

    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <security:global-method-security pre-post-annotations="enabled">
        <security:protect-pointcut expression="execution(* com.BackEnd.restful.mvc.*.*(..))"
                                   access="ROLE_DUMMY"/>
    </security:global-method-security>

The error logs:

buffer Number 2691
buffer Number 2692
buffer Number 2693
buffer Number 2694
buffer Number 2695
buffer Number 2696
buffer Number 2697
buffer Number 2698
buffer Number 2699
buffer Number 2700
Aug 15, 2016 10:36:08 PM org.springframework.web.context.request.async.WebAsyncManager setConcurrentResultAndDispatch
SEVERE: Could not complete async processing due to timeout or network error
buffer Number 0
buffer Number 1
buffer Number 2
buffer Number 3
buffer Number 4
buffer Number 5
buffer Number 6
buffer Number 7
buffer Number 8
buffer Number 9
buffer Number 10
buffer Number 11
buffer Number 12
like image 758
Shaofan Qi Avatar asked Aug 15 '16 14:08

Shaofan Qi


1 Answers

tune the asynctimeout of your container server should solve the problem

like image 52
andrew Avatar answered Oct 12 '22 17:10

andrew