2013-07-25 3 views
0

Я пытаюсь загрузить файл с Android на сервер Tomcat под управлением Джерси. Я упаковываю его внутри почтового запроса.InputStream Infinit Loop

Это то, что я делаю в Android:

protected String doInBackground(String... params) { 
    String url = params[0]; 
    String pathToFile = params[1]; 
    HttpClient httpClient = new DefaultHttpClient(); 
    HttpContext localContext = new BasicHttpContext(); 
    HttpPost httpPost = new HttpPost(); 
    HttpResponse response = null; 
    httpPost.addHeader("Cookie", "sessionToken=~session"); 
    try { 
     httpPost.setURI(new URI(url)); 
     httpPost.setHeader("Accept", "application/json"); 
     MultipartEntity entity = new MultipartEntity(
       HttpMultipartMode.BROWSER_COMPATIBLE); 
     File file = new File(pathToFile); 
     if(!file.exists()) 
      return null; 
     FileBody fileBody = new FileBody(file); 
     entity.addPart("file", fileBody); 
     httpPost.setEntity(entity); 

     response = httpClient.execute(httpPost); 
     HttpEntity result = response.getEntity(); 
    } catch (ClientProtocolException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (URISyntaxException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch(Exception e){ 
     e.printStackTrace(); 
    } 
    return response.getStatusLine().toString(); 

На сервере я следующее:

я получаю InputStream типа "org.jvnet.mimepull.DataHead $ ReadMultiStream" и при чтении, чтение возвращается к 1024 после достижения конца файла.

@POST 
@Consumes({ MediaType.MULTIPART_FORM_DATA }) 
@Produces({ MediaType.APPLICATION_JSON }) 
public Response uploadStorageFile(@Context UriInfo ui, @Context HttpHeaders hh, @FormDataParam("file") 
InputStream uploadedInputStream, @FormDataParam("file") FormDataContentDisposition fileDetail){ 
    System.out.println(uploadedInputStream.getClass().getName()); 
    String uploadedFileLocation = fileDetail.getFileName(); 
    long size = fileDetail.getSize(); 
    // save it 
    writeToFile(uploadedInputStream); 

    String output = "File uploaded to : "; 

    return Response.status(200).entity(output).build(); 

} 
private void writeToFile(InputStream uploadedInputStream) { 

     try { 
      OutputStream out = new FileOutputStream(new File("test.jpg")); 
      int read = 0; 
      byte[] bytes = new byte[1024]; 
      while ((read = uploadedInputStream.read(bytes)) > 0) { 
       out.write(bytes, 0, read); 
      } 
      out.flush(); 
      out.close(); 
     } catch (IOException e) { 

      e.printStackTrace(); 
     } 

    } 

Если длина файла 8192, цикл выглядит следующим образом: 1024,2048,3072,4096,5120,6144,7168,8192,1024 -> почему?

Примечание: Я пробовал с условием в -1.

Может ли кто-нибудь выяснить, что происходит?

+1

Вы пробовали '> -1'? – NINCOMPOOP

+0

Боюсь, что> -1 не! = -1 работать. Значение прочитанного составляет порядка 1024,2048,3072,4096,5120,6144,7168,8192,1024. Он никогда не ударяет -1 или 0. – HeWhoCodes

+0

@JonathanDrapeau Я не хочу подключать InputStream с OutputStream. Я просто хочу захватить файл, упаковать его в пакет и распаковать его на стороне сервера ... Спасибо за комментарий – HeWhoCodes

ответ

2

Так что помогли вам решить вашу проблему, ваш последний комментарий указывает на то, что this bug was responsible.

Оба метода «чтения» на классе ReadMultiStream нарушают договор интерфейса java.io.InputStream реализован . Javadoc утверждает, что -1 должен быть возвращен на конец потока , но класс ReadMultiStream возвращает -1 только для первого вызова (в конце потока), все последующие вызовы вместо этого вызывают исключение. Эта проблема может быть смоделирована путем отправки потока символов через веб-сайт и переноса его на java.io.BufferedReader на стороне клиента. Когда поток не заканчивается новым символом строки, тогда обычное использование метода readLine терпит неудачу.

Fix версия/s: 2.2.6

+0

Это помогло выявить проблему, само решение еще не определено. Я нашел простой способ его решить (я сделаю ответ), однако, похоже, есть некоторые серьезные недостатки в ReadMultiStream. – HeWhoCodes

+0

также, что ошибка не соответствует той, с которой я столкнулся. Ошибка, с которой я столкнулся, заставляет поток перемещаться в цикле, никогда не возвращающем -1 (или исключение). Отчет об ошибках, который вы предоставили, дает -1 в первый раз, а следующее возвращает исключение, совершенно другое, но это помогло мне увидеть, что ReadMultiStream испорчен. – HeWhoCodes

0

Благодарности к Drapeau @ Джонатан, @боксировал | проблема была определена. ReadMultiStream нарушает интерфейс java.io.InputStream.

Решение было довольно просто, на стороне сервера:

@POST 
@Consumes({ MediaType.MULTIPART_FORM_DATA }) 
@Produces({ MediaType.APPLICATION_JSON }) 
public Response uploadStorageFile(@Context UriInfo ui, @Context HttpHeaders hh,  @FormDataParam("file") 
InputStream uploadedInputStream, @FormDataParam("file") FormDataContentDisposition fileDetail){ 
System.out.println(uploadedInputStream.getClass().getName()); 
String uploadedFileLocation = fileDetail.getFileName(); 
long size = fileDetail.getSize(); 
// save it 
try { 
      //test.jpg for test purposes 
    OutputStream out = new FileOutputStream(new File("test.jpg")); 
    IOUtils.copy(uploadedInputStream, out); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

String output = "File uploaded to : "; 

return Response.status(200).entity(output).build(); 

}

Несколько учебников преподавали работать InputStream (на стороне сервера), как я представил в этом вопросе, по этой причине я не Не знаю, если это недавняя ошибка.

Смежные вопросы