春季启动MultipartFile问题与ByteArrayResource [英] Spring-boot MultipartFile issue with ByteArrayResource

查看:1897
本文介绍了春季启动MultipartFile问题与ByteArrayResource的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个使用excel文件的rest api.我正在使用spring-boot,并且可以在此处获得代码.

I'm trying to implement a rest api consuming excel file. I'm using spring-boot and code is available here.

代码可以正常工作.但是我无法使代码与ByteArrayResource一起使用来代替 FileSystemResource :

Code works fine when using FileSystemResource for payload. But i'm not able to make the code work with ByteArrayResource in replacement of FileSystemResource:

RestApi.java:

@RestController
public class RestApi {
    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    @PostMapping("/api/upload")
    public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile uploadfile) {
        LOGGER.debug("Single file upload!");
        try {
            LOGGER.info("\n\n ****** File name: {}, type {}! ************", uploadfile.getOriginalFilename(), uploadfile.getContentType());
            this.processExcelFile(uploadfile.getInputStream());
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity<>("Successfully uploaded - " + uploadfile.getOriginalFilename(), new HttpHeaders(), HttpStatus.OK);
    }

    private List<String> processExcelFile(InputStream stream) throws Exception {
        List<String> result = new ArrayList<String>();      

         //Create Workbook instance holding reference to .xlsx file
         try(XSSFWorkbook workbook = new XSSFWorkbook(stream);) {
             //Get first/desired sheet from the workbook
             XSSFSheet sheet = workbook.getSheetAt(0);
             //Iterate through each rows one by one
             Iterator<Row> rowIterator = sheet.iterator();
             while (rowIterator.hasNext()) {
                 Row row = rowIterator.next();
                 String cellValue = row.getCell(0).getRichStringCellValue().toString();
                 result.add(cellValue);
                 LOGGER.info("\n\n ****** Cell value: {} ************", cellValue);
             }
            return result;
         }
    }
}

RestApiTest:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class RestApiTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private ResourceLoader loader;

    @Test
    public void testUploadFile() throws Exception {

        Resource resource = this.loader.getResource("classpath:test.xlsx");

        MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();           
//      parts.add("file", new FileSystemResource(resource.getFile()));
        parts.add("file", new ByteArrayResource(IOUtils.toByteArray(resource.getInputStream())));

        String response = this.restTemplate.postForObject("/api/upload", parts, String.class);

        Assertions.assertThat(response).containsIgnoringCase("success");
    }
}

运行测试时出现以下错误:

I'm getting following error when running test:

java.lang.AssertionError: 
Expecting:
 <"{"timestamp":1487852597527,"status":400,"error":"Bad Request","exception":"org.springframework.web.multipart.support.MissingServletRequestPartException","message":"Required request part 'file' is not present","path":"/api/upload"}">
to contain:
 <"success">
 (ignoring case)

有什么主意吗?

推荐答案

使用loader.getResource(...)时,必须使用资源本身,如上所示.因此,您不需要ByteArrayResource.我遇到了这个问题,但是我没有使用来自classpath的资源.因此,如果确实需要使用ByteArrayResource,这是我的解决方法

when using loader.getResource(...) you must use resource itself as answered above. So you don't need ByteArrayResource. I got this problem, but I'm not using resource from classpath. So if someone really need to use ByteArrayResource, here is my workaround

public class FileNameAwareByteArrayResource extends ByteArrayResource {

        private String fileName;

        public FileNameAwareByteArrayResource(String fileName, byte[] byteArray, String description) {
            super(byteArray, description);
            this.fileName = fileName;
        }

        @Override
        public String getFilename() {
            return fileName;
        }
}

然后使用它

parts.add("file", new FileNameAwareByteArrayResource("filename", byteArray));

这篇关于春季启动MultipartFile问题与ByteArrayResource的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆