2013-02-26 51 views
1

我嘗試使用GAE從blobstore上傳文件到服務器(127.0.0.1),但接收服務器給我錯誤「The上傳的文件僅部分上傳「。 我也在請求中發送一個參數,並且它由服務器正確接收。GAE上傳文件POST請求(URLConnection) - 錯誤:上傳的文件僅部分上傳

String url = "http://127.0.0.1/"; 
String charset = "UTF-8"; 

FileService fileService = FileServiceFactory.getFileService(); 
AppEngineFile appEngineFile = fileService.getBlobFile(new BlobKey("blob key")); 

String param = "my param"; 
File binaryFile = new File(appEngineFile.getFullPath()); 
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value. 
String CRLF = "\r\n"; // Line separator required by multipart/form-data. 

URLConnection connection = new URL(url).openConnection(); 
connection.setDoOutput(true); 
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); 
PrintWriter writer = null; 
try { 
    OutputStream output = connection.getOutputStream(); 
    writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important! 

    // Send normal param. 
    writer.append("--" + boundary).append(CRLF); 
    writer.append("Content-Disposition: form-data; name=\"api_password\"").append(CRLF); 
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); 
    writer.append(CRLF); 
    writer.append(param).append(CRLF).flush(); 

    // Send binary file. 
    writer.append("--" + boundary).append(CRLF); 
    writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF); 
    writer.append("Content-Type: application/octet-stream").append(CRLF); 
    writer.append("Content-Transfer-Encoding: binary").append(CRLF); 
    writer.append(CRLF).flush(); 
    InputStream input = null; 
    try { 

    BlobInfoFactory blobInfoFactory = new BlobInfoFactory(); 
    BlobInfo blobInfo = blobInfoFactory.loadBlobInfo(new BlobKey("blob key")); 
    Long blobSize = blobInfo.getSize(); 
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 

    //max read on fetch 
    long maxReadFetch = 1015807; 

    //read the file in one time temporary 
    long i = 0; 
    long start = 0; 
    long end = 0; 
    while(i < blobSize) { 

    start = i; 
    end = i + maxReadFetch; 
    //determine end 
    if(end > blobSize) { 
    end = blobSize; 
    } 
    buffer.write(blobstoreService.fetchData(new BlobKey("blob key"), start, end)); 
    i += maxReadFetch; 

    } 

    output.write(buffer.toByteArray()); 

     output.flush(); // Important! Output cannot be closed. Close of writer will close output as well. 

    } finally { 
     if (input != null) try { input.close(); } catch (IOException logOrIgnore) {} 
    } 
    writer.append(CRLF).flush(); // CRLF is important! It indicates end of binary boundary. 

    // End of multipart/form-data. 
    writer.append("--" + boundary + "--").append(CRLF); 


    //resp part 
InputStream responseStream = new BufferedInputStream(connection.getInputStream()); 

BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream)); 

StringBuilder stringBuilder = new StringBuilder(); 
String line2; 
while ((line2 = responseStreamReader.readLine()) != null) 
{ 
    stringBuilder.append(line2).append("\n"); 
} 
responseStreamReader.close(); 

String response = stringBuilder.toString(); 
resp.getWriter().write(response); 
} finally { 
    if (writer != null) writer.close(); 
} 
+0

爲什麼你寫的blob一個ByteArrayOutputStream,而不是連接錯誤的OutputStream?你喜歡用盡所有的記憶? – jtahlborn 2013-02-26 17:38:32

+0

euh否;)我應該如何發送它在循環呢? – 2013-02-26 17:41:39

+1

更改'buffer.write('到'output.write('... – jtahlborn 2013-02-26 18:12:36

回答

0

所以我修復它這裏是我的解決方案

FileService fileService = FileServiceFactory.getFileService(); 
AppEngineFile appEngineFile = fileService.getBlobFile(new BlobKey(video.getBlobkey())); 

String param = "4166764c675120921f348e64ca10148e8ff6d5df"; 
File binaryFile = new File(appEngineFile.getFullPath()); 
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value. 
String CRLF = "\r\n"; // Line separator required by multipart/form-data. 

URLConnection connection = new URL(url).openConnection(); 
connection.setDoOutput(true); 
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); 
BufferedOutputStream writer = null; 

OutputStream output = connection.getOutputStream(); 
writer = new BufferedOutputStream(output); // true = autoFlush, important! 

// Send normal param. 
writer.write(("--" + boundary + CRLF).getBytes()); 
writer.write(("Content-Disposition: form-data; name=\"api_password\"" + CRLF).getBytes()); 
writer.write(("Content-Type: text/plain; charset=" + charset + CRLF).getBytes()); 
writer.write((CRLF).getBytes()); 
writer.write((param + CRLF).getBytes()); 
writer.flush(); 

// Send binary file. 
writer.write(("--" + boundary + CRLF).getBytes()); 
writer.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + binaryFile.getName() + "\"" + CRLF).getBytes()); 
writer.write(("Content-Type: application/octet-stream" + CRLF).getBytes()); 
writer.write(("Content-Transfer-Encoding: binary" + CRLF).getBytes()); 
writer.write((CRLF).getBytes()); 
writer.flush(); 
InputStream input = null; 
try { 

    BlobInfoFactory blobInfoFactory = new BlobInfoFactory(); 
    BlobInfo blobInfo = blobInfoFactory.loadBlobInfo(new BlobKey(video.getBlobkey())); 
    Long blobSize = blobInfo.getSize(); 

    //max read on fetch 
    long maxReadFetch = 1015807; 

    //read the file in one time temporary 
    long i = 0; 
    long start = 0; 
    long end = 0; 
    while(i < blobSize) { 

     start = i; 
     end = i + maxReadFetch; 
     //determine end 
     if(end > blobSize) { 
      end = blobSize; 
     } else { 
      end--; 
     } 
     writer.write(blobstoreService.fetchData(new BlobKey(video.getBlobkey()), start, end)); 
     i += maxReadFetch; 

    } 

    writer.flush(); // Important! Output cannot be closed. Close of writer will close output as well. 

} finally { 
    if (input != null) try { input.close(); } catch (IOException logOrIgnore) {} 
} 
writer.write((CRLF).getBytes()); 
writer.flush(); // CRLF is important! It indicates end of binary boundary. 

// End of multipart/form-data. 
writer.write(("--" + boundary + "--" + CRLF).getBytes()); 
writer.flush(); 

//response part 
InputStream responseStream = new BufferedInputStream(connection.getInputStream()); 

BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream)); 

StringBuilder stringBuilder = new StringBuilder(); 
String line2; 
while ((line2 = responseStreamReader.readLine()) != null) 
{ 
    stringBuilder.append(line2).append("\n"); 
} 
responseStreamReader.close(); 

String response = stringBuilder.toString(); //JSON data 
return response; 
0

由於錯誤「上傳的文件只有部分被上傳」是從取消上傳結果,我想你的GAE請求從30年代可能執行限制或例外中止,writer.append("--" + boundary + "--").append(CRLF);發生之前。可能會輸出日誌語句以查看代碼停止的位置。