2015-12-09 1 views
3

Я пытаюсь вернуть поток файлов из веб-службы Rest, развернутой на сервере, и обрабатывать этот поток из веб-службы Rest Rest на клиенте. На сервере я использую этот код:Возврат веб-службы Spring Rest Файл как ресурс

@Override 
@RequestMapping(value = "/file", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) 
public @ResponseBody Resource getAcquisition(@RequestParam(value="filePath", required = true) String filePath) throws FileNotFoundException{ 
    // acquiring the stream 
    File file= new File(filePath); 
    InputStream stream = new FileInputStream(file); 
    // counting the length of data 
    final long contentLength = file.length() ; 

    return new InputStreamResource(stream){ 
     @Override 
     public long contentLength() throws IOException { 
      return contentLength; 
     } 
    }; 
} 

и, на данный момент, на клиенте я использую это (тогда я должен записать файл в файловой системе)

@Override 
public void getFile(String serverIp, String toStorePath, String filePath) throws Exception{ 
    RestTemplate restTemplate = new RestTemplate(); 
    Resource resource = restTemplate.getForObject(serverIp + "ATS/client/file/?filePath={filePath}",Resource.class, filePath); 
    File file=resource.getFile(); 
    System.out.println(file.length()); 
} 

Но сервер вернуть это исключение:

ERROR com.controller.ErrorController - org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation 
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:195) 
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:100) 
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:166) 
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80) 
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:127) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729) 
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) 
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) 
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) 
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) 
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) 
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) 
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526) 
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
at java.lang.Thread.run(Thread.java:745) 

Я попытался даже без MediaType buut он не работает. Я отправляю также мою конфигурацию пружины:

package com.config.core; 

import java.util.List; 
import java.util.Properties; 

import org.apache.commons.dbcp.BasicDataSource; 
import org.hibernate.jpa.HibernatePersistenceProvider; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.Import; 
import org.springframework.context.annotation.PropertySource; 
import org.springframework.core.env.Environment; 
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 
import org.springframework.http.converter.HttpMessageConverter; 
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 
import org.springframework.orm.jpa.JpaTransactionManager; 
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 
import org.springframework.transaction.annotation.EnableTransactionManagement; 
import org.springframework.web.multipart.commons.CommonsMultipartResolver; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 
import org.thymeleaf.spring4.SpringTemplateEngine; 
import org.thymeleaf.spring4.view.ThymeleafViewResolver; 
import org.thymeleaf.templateresolver.ServletContextTemplateResolver; 

import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module; 


/** 
* All the configuration bean 
* 
*/ 
@EnableWebMvc 
@Configuration 
@PropertySource(value = { "classpath:application.properties" }) 
@ComponentScan({ "com.*" }) 
@EnableTransactionManagement 
@Import({ SpringMvcInitializer.class }) 
@EnableJpaRepositories("com.repository") 
public class AppConfig extends WebMvcConfigurerAdapter{ 
    @Autowired 
    private Environment env; 

    private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver"; 
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password"; 
    private static final String PROPERTY_NAME_DATABASE_URL = "db.url"; 
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username"; 

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect"; 
// private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql"; 
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan"; 
    private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql"; 


/** 
* li utilizzavo prima quando facevo l'autenticazione, vedere come fare ora che ho messo nelle proprietà il percorso com.domain 
* @return 
*/ 
// @Bean 
// public SessionFactory sessionFactory() { 
//  LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource()); 
//  builder 
//  .scanPackages(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN)) 
//  .addProperties(getHibernateProperties()); 
// 
//  return builder.buildSessionFactory(); 
// } 
// @Bean 
// public HibernateTransactionManager txManager() { 
//  return new HibernateTransactionManager(sessionFactory()); 
// } 

    /** 
    * This and the next methods are used to avoid exception while jackson mapping the entity, so fields are setted with null value 
    * unless use Hibernate.initialize 
    * @return 
    */ 
    public MappingJackson2HttpMessageConverter jacksonMessageConverter(){ 
     MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); 

     ObjectMapper mapper = new ObjectMapper(); 
     //Registering Hibernate4Module to support lazy objects 
     mapper.registerModule(new Hibernate4Module()); 

     messageConverter.setObjectMapper(mapper); 
     return messageConverter; 

    } 

    @Override 
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
     //Here we add our custom-configured HttpMessageConverter 
     converters.add(jacksonMessageConverter()); 
     super.configureMessageConverters(converters); 
    } 

    private Properties getHibernateProperties() { 
     Properties properties = new Properties(); 
     properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT)); 
//  properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL)); 
     properties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL)); 
     properties.put("hibernate.enable_lazy_load_no_trans",true); 
     return properties; 
    } 

    @Bean(name = "dataSource") 
    public BasicDataSource dataSource() { 
     BasicDataSource ds = new BasicDataSource(); 
     ds.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER)); 
     ds.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL)); 
     ds.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME)); 
     ds.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD)); 
     return ds; 
    } 

    @Bean 
    public ServletContextTemplateResolver TemplateResolver(){ 
     ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); 
     resolver.setPrefix("/WEB-INF/templates/pages/"); 
     resolver.setSuffix(".html"); 
     resolver.setTemplateMode("LEGACYHTML5"); 
     resolver.setCacheable(false); 
     return resolver; 
     /*ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); 
     resolver.setPrefix("/WEB-INF/pages/"); 
     resolver.setSuffix(".html"); 
     resolver.setTemplateMode("HTML5"); 
     return resolver;*/ 
    } 

    @Bean 
    public SpringTemplateEngine templateEngine(){ 
     SpringTemplateEngine templateEngine = new SpringTemplateEngine(); 
     templateEngine.setTemplateResolver(TemplateResolver()); 
     return templateEngine; 
    } 


    @Bean 
    public ThymeleafViewResolver viewResolver() { 
     ThymeleafViewResolver resolver = new ThymeleafViewResolver(); 
     resolver.setTemplateEngine(templateEngine()); 
     resolver.setOrder(1); 
     resolver.setViewNames(new String[]{"*", "js/*", "template/*"}); 
     return resolver; 
    } 

    /** 
    * Register multipartResolver for file upload 
    * @return 
    */ 
    @Bean 
    public CommonsMultipartResolver multipartResolver() { 
     CommonsMultipartResolver resolver=new CommonsMultipartResolver(); 
     resolver.setDefaultEncoding("utf-8"); 
     return resolver;  
    } 

    /** 
    * Allow use of bootstrap 
    */ 
    @Override 
    public void addResourceHandlers(ResourceHandlerRegistry registry) { 
      registry.addResourceHandler("/static/**") 
        .addResourceLocations("/static/"); 
    } 

    /** 
    * Allow use of JPA 
    */ 
    @Bean 
    public JpaTransactionManager transactionManager() { 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); 
     return transactionManager; 
    } 
    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
     LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 
     entityManagerFactoryBean.setDataSource(dataSource()); 
     entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class); 
     entityManagerFactoryBean.setPackagesToScan(env. 
     getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN)); 
     entityManagerFactoryBean.setJpaProperties(getHibernateProperties()); 
     return entityManagerFactoryBean; 

    } 
} 

Знаете ли вы эту проблему Благодаря

Update:

@Override 
@RequestMapping(value = "/file", method = RequestMethod.GET) 
public ResponseEntity<Resource> getAcquisition(HttpServletResponse resp,@RequestParam(value="filePath", required = true) String filePath) throws FileNotFoundException{ 
    HttpHeaders headers = new HttpHeaders(); 
    headers.setContentType(MediaType.TEXT_PLAIN); 
    resp.setContentType("application/octet-stream"); 
    File file= new File(filePath); 
    InputStream stream = new FileInputStream(file); 
    InputStreamResource inputStreamResource = new InputStreamResource(stream); 
    return new ResponseEntity<Resource>(inputStreamResource, null, HttpStatus.OK); 
} 

но получить

Could not write content: No serializer found for class java.io.FileDescriptor 
+0

кажется, что нет никакого способа, чтобы преобразовать InputStreamResource в ресурс как это делает @ResponseBody. Возможно, это может помочь: http://stackoverflow.com/questions/5673260/downloading-a-file-from-spring-controllers –

+0

Я пытался с IOUtils, но он не работает, он пишет на веб-сервере, а не на клиенте боковая сторона. Я следую этому руководству http://forketyfork.blogspot.it/2013/06/how-to-return-file-stream-or-classpath.html – luca

ответ

0

Вы можете использовать ResponseEntity вместо @ ResponseBody

@RequestMapping(value = "/file", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) 
    public ResponseEntity getAcquisition(@RequestParam(value="filePath", required = true) String filePath) throws FileNotFoundException{ 

     // ... some code  

     InputStreamResource inputStreamResource = new InputStreamResource(inputStream); 
     httpHeaders.setContentLength(contentLengthOfStream); 
     return new ResponseEntity(inputStreamResource, httpHeaders, HttpStatus.OK); 
    } 
+0

Я получаю «Серийный анализатор не найден для класса java.io.FileDescriptor и никаких свойств, обнаруженных для создания BeanSerializer '. Я также попробовал с возвратом new ResponseEntity (новый FileSystemResource (новый файл (filePath)), null, HttpStatus.OK); – luca

+0

Удалите созданные и используйте ResponseEntity вместо ResponseEntity, также добавьте тип содержимого в заголовки и заголовки ответов.setContentType (MediaType.IMAGE_GIF); response.setContentType ("image/gif"); – reos

+0

Я отправил обновленный метод, но получаю исключение – luca

2

Это, как я установил вопрос

@Bean 
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { 
    MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); 

    ObjectMapper objectMapper = new ObjectMapper(); 
    objectMapper.registerModule(new Hibernate4Module()); 
    objectMapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false); 
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 

    messageConverter.setObjectMapper(objectMapper); 
    return messageConverter; 
} 


@Override 
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
    converters.add(mappingJackson2HttpMessageConverter()); 
    converters.add(new ResourceHttpMessageConverter()); 
    super.configureMessageConverters(converters); 
} 

Я добавил ResourceHttpMessageConverter в список преобразователей.

Вот ресурс:

@RequestMapping(value="/file/{uniqueKey}", method = RequestMethod.GET) 
@ResponseBody 
public FileSystemResource getUserFile(HttpServletResponse response, @PathVariable String uniqueKey){ 

    Map<String, String> metadata = authService.getUserFileMetadataByUniqueKey(uniqueKey); 

    final File file = new File(metadata.get("filePath")); 
    response.setContentType(metadata.get("contentType")); 
    response.setHeader("Content-Disposition", "attachment; filename="+metadata.get("fileUniqueName")); 

    return new FileSystemResource(file); 
}