2016-04-27 4 views
2

Я пытаюсь загрузить несколько файлов с одним запросом http get в моем приложении spring-mvc.Загрузить несколько файлов Java Spring

Я смотрел другие сообщения, говоря, что вы можете просто заархивировать файл и отправить этот файл, но он не идеален в моем случае, так как файл не находится в прямом доступе от приложения. Чтобы получить файлы, я должен запросить интерфейс REST, который передает файл из hbase или hadoop.

У меня могут быть файлы размером более 1 Go, поэтому загрузка файлов в репозиторий, их замена и отправка их клиенту будут слишком длинными. (Учитывая, что большой файл уже является zip, zipping не сжимает их).

Я видел here и there, которые вы можете использовать multipart-response, чтобы загрузить сразу несколько файлов, но я не могу получить никакого результата. Вот мой код:

String boundaryTxt = "--AMZ90RFX875LKMFasdf09DDFF3"; 
response.setContentType("multipart/x-mixed-replace;boundary=" + boundaryTxt.substring(2)); 
ServletOutputStream out = response.getOutputStream(); 

// write the first boundary 
out.write(("\r\n"+boundaryTxt+"\r\n").getBytes()); 

String contentType = "Content-type: application/octet-stream\n"; 

for (String s:files){ 
    System.out.println(s); 
    String[] split = s.trim().split("/"); 
    db = split[1]; 
    key = split[2]+"/"+split[3]+"/"+split[4]; 
    filename = split[4]; 

    out.write((contentType + "\r\n").getBytes()); 
    out.write(("\r\nContent-Disposition: attachment; filename=" +filename+"\r\n").getBytes()); 

    InputStream is = null; 
    if (db.equals("hadoop")){ 
     is = HadoopUtils.get(key); 
    } 
    else if (db.equals("hbase")){ 
     is = HbaseUtils.get(key); 
    } 
    else{ 
     System.out.println("Wrong db with name: " + db); 
    } 
    byte[] buffer = new byte[9000]; // max 8kB for http get 
    int data; 
    while((data = is.read(buffer)) != -1) { 
     out.write(buffer, 0, data); 
    } 
    is.close(); 

    // write bndry after data 
    out.write(("\r\n"+boundaryTxt+"\r\n").getBytes()); 
    response.flushBuffer(); 
    } 
// write the ending boundary 
out.write((boundaryTxt + "--\r\n").getBytes()); 
response.flushBuffer(); 
out.close(); 
} 

Странная часть заключается в том, что я получаю другой результат в зависимости от навигатора. Ничего не происходит в Chrome (посмотрел на консоль) и в Firefox, я получил приглашение для загрузки для каждого файла, но у него нет нужного типа или правильного имени (ничего в консоли тоже).

Есть ошибки в моем коде? Если нет, есть ли альтернатива?

Редактировать

Я также видел этот пост: Unable to send a multipart/mixed request to spring MVC based REST service

Редактировать 2

firefox result

Содержание этого файла, что я хочу, но почему не может Я получаю правильное имя и почему хром не может скачать что-нибудь?

+0

Вы можете загрузить петлю на запросы в JS, и после каждого запроса закончена новая загрузка запускается. Я думаю, что это кажется проще, чем взломать, чтобы запускать несколько загрузок. –

+0

@WeareBorg У меня есть только базовые знания в js, можете ли вы дать мне некоторые ресурсы для этого? – Whitefret

+0

К сожалению, нет, я разработчик базы данных, даже не знаю JS. Я могу дать вам код для загрузки ZIP, если вы хотите в Java, что у меня есть ... –

ответ

2

Это так, как вы можете сделать загрузку с помощью почтового индекса:

try { 
     List<GroupAttachments> groupAttachmentsList = attachIdList.stream().map(this::getAttachmentObjectOnlyById).collect(Collectors.toList()); // Get list of Attachment objects 
      Person person = this.personService.getCurrentlyAuthenticatedUser(); 
      String zipSavedAt = zipLocation + String.valueOf(new BigInteger(130, random).toString(32)); // File saved location 
      byte[] buffer = new byte[1024]; 
      FileOutputStream fos = new FileOutputStream(zipSavedAt); 
      ZipOutputStream zos = new ZipOutputStream(fos); 

       GroupAttachments attachments = getAttachmentObjectOnlyById(attachIdList.get(0)); 

        for (GroupAttachments groupAttachments : groupAttachmentsList) { 
          Path path = Paths.get(msg + groupAttachments.getGroupId() + "/" + 
            groupAttachments.getFileIdentifier()); // Get the file from server from given path 
          File file = path.toFile(); 
          FileInputStream fis = new FileInputStream(file); 
          zos.putNextEntry(new ZipEntry(groupAttachments.getFileName())); 
          int length; 

          while ((length = fis.read(buffer)) > 0) { 
           zos.write(buffer, 0, length); 
          } 
          zos.closeEntry(); 
          fis.close(); 

        zos.close(); 
        return zipSavedAt; 
      } 
     } catch (Exception ignored) { 
     } 
     return null; 
    } 

метод управления для загрузки почтового индекса:

@RequestMapping(value = "/URL/{mode}/{token}") 
    public void downloadZip(HttpServletResponse response, @PathVariable("token") String token, 
          @PathVariable("mode") boolean mode) { 
     response.setContentType("application/octet-stream"); 
     try { 
      Person person = this.personService.getCurrentlyAuthenticatedUser(); 
      List<Integer> integerList = new ArrayList<>(); 
      String[] integerArray = token.split(":"); 
      for (String value : integerArray) { 
       integerList.add(Integer.valueOf(value)); 
      } 
      if (!mode) { 
       String zipPath = this.groupAttachmentsService.downloadAttachmentsAsZip(integerList); 
       File file = new File(zipPath); 
       response.setHeader("Content-Length", String.valueOf(file.length())); 
       response.setHeader("Content-Disposition", "attachment; filename=\"" + person.getFirstName() + ".zip" + "\""); 
       InputStream is = new FileInputStream(file); 
       FileCopyUtils.copy(IOUtils.toByteArray(is), response.getOutputStream()); 
       response.flushBuffer(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

Веселитесь, упаковывает сомнения, Леммы знают.

Update

байт-массив в ZIP-файле. Вы можете использовать этот код в цикле, как и в первом методе я дал:

public static byte[] zipBytes(String filename, byte[] input) throws IOException { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ZipOutputStream zos = new ZipOutputStream(baos); 
    ZipEntry entry = new ZipEntry(filename); 
    entry.setSize(input.length); 
    zos.putNextEntry(entry); 
    zos.write(input); 
    zos.closeEntry(); 
    zos.close(); 
    return baos.toByteArray(); 
} 
Смежные вопросы