Подтвердить что ты не робот

Как получить загрузку файла в spring mvc, используя кодировку multipart/form и chunked?

Я пытаюсь написать метод spring mvc, который может получать как многостраничную, так и передаваемую передачу файлов. Я могу написать отдельный метод для обработки каждого типа, но я хотел бы сделать это с помощью одного и того же метода, поэтому я могу использовать один и тот же REST POST uri, например:

http://host:8084/attachments/testupload

Вот моя лучшая попытка:

@RequestMapping(value = { "/testupload" }, method = RequestMethod.POST, produces = 
  "application/json")
public @ResponseBody
ResponseEntity<MessageResponseModel> testUpload(
  @RequestParam(value = "filedata", required = false) MultipartFile filedata,
  final HttpServletRequest request) throws IOException {

  InputStream is = null;
  if (filedata == null) {
    is = request.getInputStream();
  }
  else {
    is = filedata.getInputStream();
  }
  byte[] bytes = IOUtils.toByteArray(is);
  System.out.println("read " + bytes.length + " bytes.");

  return new ResponseEntity<MessageResponseModel>(null, null, HttpStatus.OK);
}

Используя вышеописанный метод, я могу загрузить многостраничный файл, но если я загружу фрагментированный файл, я получаю исключение из spring, который гласит:

org.springframework.web.multipart.MultipartException: \
The current request is not a multipart request

Если я удалю параметр запроса MultipartFile, он отлично работает для кодирования передачи. Если я оставлю его, он отлично работает для загрузки MultipartFile. Как я могу сделать это с помощью того же метода для обработки обоих типов загрузки?

Это отлично работает для chunked:

@RequestMapping(value = { "/testupload" }, method = RequestMethod.POST, produces = 
  "application/json")
public @ResponseBody
ResponseEntity<MessageResponseModel> testUpload(
  final HttpServletRequest request) throws IOException {

  InputStream is = null;
  is = request.getInputStream();
  byte[] bytes = IOUtils.toByteArray(is);
  System.out.println("read " + bytes.length + " bytes.");

  return new ResponseEntity<MessageResponseModel>(null, null, HttpStatus.OK);
}

и это отлично работает для MultipartFile:

@RequestMapping(value = { "/testupload" }, method = RequestMethod.POST, produces = 
  "application/json")
public @ResponseBody
ResponseEntity<MessageResponseModel> testUpload(
  @RequestParam MultipartFile filedata) throws IOException {

  InputStream is = null;
  is = filedata.getInputStream();
  byte[] bytes = IOUtils.toByteArray(is);
  System.out.println("read " + bytes.length + " bytes.");

  return new ResponseEntity<MessageResponseModel>(null, null, HttpStatus.OK);
}

Должно быть возможно, кто-нибудь знает, как это сделать?

Спасибо, Стив

4b9b3361

Ответ 1

Выдержка из моего кода (Spring 3.2, загрузка файла blueimp с помощью AngularJS):

/**
 * Handles chunked file upload, when file exceeds defined chunked size.
 * 
 * This method is also called by modern browsers and IE >= 10
 */
@RequestMapping(value = "/content-files/upload/", method = RequestMethod.POST, headers = "content-type!=multipart/form-data")
@ResponseBody
public UploadedFile uploadChunked(
        final HttpServletRequest request,
        final HttpServletResponse response) {

    request.getHeader("content-range");//Content-Range:bytes 737280-819199/845769
    request.getHeader("content-length"); //845769
    request.getHeader("content-disposition"); // Content-Disposition:attachment; filename="Screenshot%20from%202012-12-19%2017:28:01.png"
    request.getInputStream(); //actual content.

    //Regex for content range: Pattern.compile("bytes ([0-9]+)-([0-9]+)/([0-9]+)");
    //Regex for filename: Pattern.compile("(?<=filename=\").*?(?=\")");

    //return whatever you want to json
    return new UploadedFile();
}

/**
 * Default Multipart file upload. This method should be invoked only by those that do not
 * support chunked upload.
 * 
 * If browser supports chunked upload, and file is smaller than chunk, it will invoke
 * uploadChunked() method instead.
 * 
 * This is instead a fallback method for IE <=9
 */
@RequestMapping(value = "/content-files/upload/", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
@ResponseBody
public HttpEntity<UploadedFile> uploadMultipart(
        final HttpServletRequest request,
        final HttpServletResponse response,
        @RequestParam("file") final MultipartFile multiPart) {

    //handle regular MultipartFile

    // IE <=9 offers to save file, if it is returned as json, so set content type to plain.
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.TEXT_PLAIN);
    return new HttpEntity<>(new UploadedFile(), headers);
}

Это должно помочь вам начать. Минимальное тестирование выполняется на IE8, IE9, IE10, Chrome, FF. Конечно, могут быть проблемы, и, вероятно, есть более простой способ извлечения диапазонов контента, но... работает для меня.

Ответ 2

Вот контроллер для этого

package com.faisalbhagat.web.controller;

@Controller
@RequestMapping(value = { "" })
public class UploadController {

    @RequestMapping(value = "/uploadMyFile", method = RequestMethod.POST)
    @ResponseBody
    public String handleFileUpload(MultipartHttpServletRequest request)
            throws Exception {
        Iterator<String> itrator = request.getFileNames();
        MultipartFile multiFile = request.getFile(itrator.next());
                try {
            // just to show that we have actually received the file
            System.out.println("File Length:" + multiFile.getBytes().length);
            System.out.println("File Type:" + multiFile.getContentType());
            String fileName=multiFile.getOriginalFilename();
            System.out.println("File Name:" +fileName);
            String path=request.getServletContext().getRealPath("/");

            //making directories for our required path.
            byte[] bytes = multiFile.getBytes();
            File directory=    new File(path+ "/uploads");
            directory.mkdirs();
            // saving the file
            File file=new File(directory.getAbsolutePath()+System.getProperty("file.separator")+picture.getName());
            BufferedOutputStream stream = new BufferedOutputStream(
                    new FileOutputStream(file));
            stream.write(bytes);
            stream.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new Exception("Error while loading the file");
        }
        return toJson("File Uploaded successfully.")
    }

    public String toJson(Object data)
    {
        ObjectMapper mapper=new ObjectMapper();
        StringBuilder builder=new StringBuilder();
        try {
            builder.append(mapper.writeValueAsString(data));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return builder.toString();
    }
}

вы можете найти решение для решения с кодом на стороне клиента http://faisalbhagat.blogspot.com/2014/09/springmvc-fileupload-with-ajax-and.html