Проблема MultipartFile, невозможно преобразовать в файл - PullRequest
1 голос
/ 05 ноября 2019

Я пытаюсь загрузить файл размером более 1 ГБ, я использую Spring Boot.

Я пробовал с приведенным ниже кодом, но я получаю сообщение об ошибке Out of Memory.

public void uploadFile(MultipartFile file) throws IOException {
        try {       
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setBufferRequestBody(false);
            restTemplate.setRequestFactory(requestFactory);

            String uploadFile= restTemplate.exchange(url, HttpMethod.POST,
                new HttpEntity<>(new FileSystemResource(convert(file)), headers), String.class).getBody();

        } catch (Exception e) {
            throw new RuntimeException("Exception Occured", e);
        }
    }


    private static File convert(MultipartFile file) throws IOException {
        File convFile = new File(file.getOriginalFilename());
        convFile.createNewFile();
        FileOutputStream fos = new FileOutputStream(convFile);
        fos.write(file.getBytes());
        fos.close();
        return convFile;    
    }

Основная проблема, с которой я сталкиваюсь, заключается в том, что я не могу преобразовать MultipartFile в java.io.File.

Я даже пытался заменить FileSystemResource на ByteArrayResource, но все еще получаю ошибку OOM.

Я даже пытался использовать приведенный ниже код:

private static File convert(MultipartFile file) throws IOException {
        CommonsMultipartFile commonsMultipartFile = (CommonsMultipartFile) multipartFile;
        FileItem fileItem = commonsMultipartFile.getFileItem();
        DiskFileItem diskFileItem = (DiskFileItem) fileItem;
        String absPath = diskFileItem.getStoreLocation().getAbsolutePath();
        File file = new File(absPath);  
    }

Но я получаю исключение ниже указанного фрагмента:

org.springframework.web. multipart.commons.CommonsMultipartFile не может быть приведен к org.springframework.web.multipart.MultipartFile

  1. Может кто-нибудь сказать мне, как преобразовать MultipartFile в java.io.File?

  2. А также есть ли какой-либо другой подход лучше, чем FileSystemResource bcoz Мне придется каждый раз создавать новый файл на сервере перед загрузкой. Если размер файла превышает 1 ГБ, необходимо создать еще один новый файл размером 1 ГБ на стороне сервера и вручную удалить этот файл, что лично мне не понравилось при таком подходе.

1 Ответ

3 голосов
/ 05 ноября 2019

getBytes() пытается загрузить весь байтовый массив в память, что приводит к тому, что OOM необходимо выполнить потоковую передачу файла и записать его.

Попробуйте выполнить следующее:

private static Path convert(MultipartFile file) throws IOException {
  Path newFile = Paths.get(file.getOriginalFilename());
  try(InputStream is = file.getInputStream();
     OutputStream os = Files.newOutputStream(newFile))) {
     byte[] buffer = new byte[4096];
     int read = 0;
     while((read = is.read(buffer)) > 0) {
       os.write(buffer,0,read);
     }
  }
  return newFile;  
}

Я изменил ваш метод, чтобы он возвращал Path вместо File, который является частью пакета java.nio. Пакет предпочтительнее java.io, так как он был оптимизирован больше.

Если вам нужен объект File, вы можете вызвать newFile.toFile()

, так как он возвращает объект Path, который выможно использовать класс java.nio.file.Files, чтобы переместить файл в предпочтительный каталог после его записи

private static void relocateFile(Path original, Path newLoc) throws IOException {
  if(Files.isDirectory(newLoc)) {
    newLoc = newLoc.resolve(original.getFileName());
  }
  Files.move(original, newLoc);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...