【问题标题】:graphql-spring-boot upload binarygraphql-spring-boot 上传二进制文件
【发布时间】:2018-06-11 13:00:04
【问题描述】:

我正在尝试将 GraphQL 突变和图像上传为应用程序/表单数据。 GraphQL 部分正在工作,但我想“保存”上传的二进制文件并将路径添加到 GraphQL 数据。在 createGraphQLContext 我可以访问 HttpServletRequest 但(多)部分是空的。 我使用带有嵌入式 tomcat 8.5 的 graphql-spring-boot-starter 和提供的 GraphQL Java Tools

这是我对 /graphql 的 Relay Modern 调用

------WebKitFormBoundaryWBzwQyVX0TvBTIBD
Content-Disposition: form-data; name="query"

mutation CreateProjectMutation(
  $input: ProjectInput!
) {
  createProject(input: $input) {
    id
    name
  }
}

------WebKitFormBoundaryWBzwQyVX0TvBTIBD
Content-Disposition: form-data; name="variables"

{"input":{"name":"sdasas"}}
------WebKitFormBoundaryWBzwQyVX0TvBTIBD
Content-Disposition: form-data; name="file"; filename="51zvT5zy44L._SL500_AC_SS350_.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryWBzwQyVX0TvBTIBD--

在我的@Component public class MyGraphQLContextBuilder implements GraphQLContextBuilder 中,我可以访问HttpServletRequest,并希望使用req.getPart( "file" ) 访问该文件

但我在请求中的部分是空的 intellij debugger

我已将此添加到我的 application.yml

spring:
    http:
      multipart:
        enabled: true
        file-size-threshold: 10MB
        location: /tmp
        max-file-size: 10MB
        max-request-size: 15MB
        resolve-lazily: false

并尝试了不同的@configuration 来启用多部分配置,但部分仍然是空的。

@Configuration
public class MultipartConfig {

    @Bean
    public MultipartResolver multipartResolver() {
        StandardServletMultipartResolver resolver = new StandardServletMultipartResolver();
        return resolver;
    }

}

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MyInitializer
        extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { MultipartConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/graphql" };
    }

    @Override
    protected void customizeRegistration(Dynamic registration) {

        //Parameters:-
        //   location - the directory location where files will be stored
        //   maxFileSize - the maximum size allowed for uploaded files
        //   maxRequestSize - the maximum size allowed for multipart/form-data requests
        //   fileSizeThreshold - the size threshold after which files will be written to disk
        MultipartConfigElement multipartConfig = new MultipartConfigElement("/tmp", 1048576,
                10485760, 0);
        registration.setMultipartConfig(multipartConfig);
    }
}

我不知道该怎么做。希望有人可以帮助我。

谢谢。

【问题讨论】:

    标签: java spring spring-boot graphql


    【解决方案1】:

    Spring boot 的嵌入式 Tomcat 默认支持 Servlet 3.x 多部分。 GraphQL java servlet 支持 commons FileUpload。要使事情正常工作,您必须禁用 Spring Boots 默认的多部分配置,例如:

    在 pom.xml 中为 commons-fileupload 添加 maven 依赖

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
    

    Application.yml

    spring:
        servlet:
          multipart:
             enabled: false
    

    Spring Boot 应用类

    @EnableAutoConfiguration(exclude={MultipartAutoConfiguration.class})
    

    然后在你的@Configuration 中添加一个@Bean

    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(100000);
        return multipartResolver;
    }
    

    现在您可以在 GraphQL 上下文中找到上传的多部分文件,因为它们会自动映射到:

    environment -> context -> files
    

    可从 DataFetchingEnvironment

    访问

    以及突变的实现示例:

    @Component
    public class Mutation implements GraphQLMutationResolver {
    
        @Autowired
        private TokenService tokenService;
    
        @Autowired
        private UserRepository userRepository;
    
        @Autowired
        private UserService userService;
    
        @Autowired
        private ProjectRepository repository;
    
        @Autowired
        @Qualifier( value = "modeshape" )
        private StorageService storageService;
    
        @GraphQLField @GraphQLRelayMutation
        public ProjectItem createProject( CreateProjectInput input, DataFetchingEnvironment environment ) {
            Project project = new Project( input.getName() );
            project.setDescription( input.getDescription() );
            GraphQLContext context = environment.getContext();
            Optional<Map<String, List<FileItem>>> files = context.getFiles();
            files.ifPresent( keys -> {
                List<FileItem> file = keys.get( "file" );
                List<StorageService.FileInfo> storedFiles = file.stream().map( f -> storageService.store( f, "files", true ) ).collect( Collectors.toList() );
                project.setFile( storedFiles.get( 0 ).getUuid() );
            } );
            repository.save( project );
            return new ProjectItem( project );
        }
    class CreateProjectInput {
        private String name;
        private String description;
        private String clientMutationId;
    
        @GraphQLField
        public String getName() {
            return name;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription( String description ) {
            this.description = description;
        }
    
        @GraphQLField
        public String getClientMutationId() {
            return clientMutationId;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-18
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2012-11-24
      • 2017-12-30
      • 2013-05-12
      • 2011-07-21
      • 1970-01-01
      相关资源
      最近更新 更多