2012-03-16 7 views
6

के साथ बड़ी फ़ाइल वाली पोस्ट मल्टीपार्ट/फॉर्म-डेटा इसलिए मैं बड़ी छवि फ़ाइल के साथ एक मल्टीपार्ट/फॉर्म-डेटा पोस्ट अनुरोध भेजने की कोशिश कर रहा हूं। मैं बाइट सरणी में फ़ाइल को पूर्व-रूपांतरित नहीं कर सकता, मेरा ऐप आउटऑफमेमरी अपवाद के साथ क्रैश हो जाएगा, इसलिए मुझे सीधे फ़ाइल के सामग्रियों को कनेक्शन के आउटपुटस्ट्रीम पर लिखना होगा। साथ ही, मेरा सर्वर खंडित मोड का समर्थन नहीं करता है, इसलिए मुझे डेटा भेजने से पहले सामग्री की लंबाई की गणना करना है और कनेक्शन के सेटफिक्स्डलेथस्ट्रीमिंग मोड का उपयोग करना है।HTTPURL कनेक्शन - फिक्स्ड लम्बाईस्ट्रीमिंग मोड

public void createImagePostWithToken(String accessToken, String text, 
     String type, String imagePath) { 

    URL imageUrl = null; 
    String lineEnd = "\r\n"; 
    String twoHyphens = "--"; 

    // generating byte[] boundary here 

    HttpURLConnection conn = null; 
    DataOutputStream outputStream = null; 
    DataInputStream inputStream = null; 

    int bytesRead, bytesAvailable, bufferSize; 
    byte[] buffer; 
    int maxBufferSize = 1*1024*1024; 

    try 
    { 
     long contentLength; 
     int serverResponseCode; 
     String serverResponseMessage; 
     File file = new File(imagePath);    
     FileInputStream fileInputStream = new FileInputStream(file); 
     imageUrl = buildUri("posts").toURL(); 
     conn = (HttpURLConnection)imageUrl.openConnection(); 
     conn.setConnectTimeout(30000); 
     conn.setReadTimeout(30000); 
     conn.setDoOutput(true); 
     conn.setDoInput(true);   
     conn.setRequestMethod("POST"); 
     conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);    

     String stringForLength = new String(); 

     stringForLength += "Content-Type: multipart/form-data;boundary=" + boundary; 

     stringForLength += twoHyphens + boundary + lineEnd + "Content-Disposition: form-data; name=\"access_token\"" + lineEnd; 
     stringForLength += "Content-Type: text/plain;charset=UTF-8" + lineEnd + "Content-Length: " + accessToken.length() + lineEnd + lineEnd; 
     stringForLength += accessToken + lineEnd + twoHyphens + boundary + lineEnd; 

     stringForLength += "Content-Disposition: form-data; name=\"text\"" + lineEnd; 
     stringForLength += "Content-Type: text/plain;charset=UTF-8" + lineEnd + "Content-Length: " + text.length() + lineEnd + lineEnd; 
     stringForLength += text + lineEnd + twoHyphens + boundary + lineEnd; 

     stringForLength += "Content-Disposition: form-data; name=\"type\"" + lineEnd; 
     stringForLength += "Content-Type: text/plain;charset=UTF-8" + lineEnd + "Content-Length: " + type.length() + lineEnd + lineEnd; 
     stringForLength += type + lineEnd + twoHyphens + boundary + lineEnd; 

     stringForLength += twoHyphens + boundary + lineEnd + "Content-Disposition: form-data; name=\"image\"" + lineEnd; 
     stringForLength += "Content-Type: application/octet-stream" + lineEnd + "Content-Length: " + file.length() + lineEnd + lineEnd; 
     stringForLength += lineEnd + twoHyphens + boundary + twoHyphens + lineEnd; 

     int totalLength = stringForLength.length() + (int)file.length();   
     conn.setFixedLengthStreamingMode(totalLength); 


     outputStream = new DataOutputStream(conn.getOutputStream());   
     outputStream.writeBytes(twoHyphens + boundary + lineEnd); 

     // access token 

     outputStream.writeBytes("Content-Disposition: form-data; name=\"access_token\"" + lineEnd); 
     outputStream.writeBytes("Content-Type: text/plain;charset=UTF-8" + lineEnd); 
     outputStream.writeBytes("Content-Length: " + accessToken.length() + lineEnd); 
     outputStream.writeBytes(lineEnd); 
     outputStream.writeBytes(accessToken + lineEnd); 
     outputStream.writeBytes(twoHyphens + boundary + lineEnd); 

     // text 

     outputStream.writeBytes("Content-Disposition: form-data; name=\"text\"" + lineEnd); 
     outputStream.writeBytes("Content-Type: text/plain;charset=UTF-8" + lineEnd); 
     outputStream.writeBytes("Content-Length: " + text.length() + lineEnd); 
     outputStream.writeBytes(lineEnd); 
     outputStream.writeBytes(text + lineEnd); 
     outputStream.writeBytes(twoHyphens + boundary + lineEnd); 

     // type 

     outputStream.writeBytes("Content-Disposition: form-data; name=\"type\"" + lineEnd); 
     outputStream.writeBytes("Content-Type: text/plain;charset=UTF-8" + lineEnd); 
     outputStream.writeBytes("Content-Length: " + type.length() + lineEnd); 
     outputStream.writeBytes(lineEnd); 
     outputStream.writeBytes(type + lineEnd); 
     outputStream.writeBytes(twoHyphens + boundary + lineEnd); 

     // image 

     outputStream.writeBytes(twoHyphens + boundary + lineEnd); 
     outputStream.writeBytes("Content-Disposition: form-data; name=\"image\"" + lineEnd); 
     //outputStream.writeBytes(lineEnd); 
     outputStream.writeBytes("Content-Type: application/octet-stream" + lineEnd); 
     outputStream.writeBytes("Content-Length: " + file.length() + lineEnd); 
     outputStream.writeBytes(lineEnd);   

     bytesAvailable = fileInputStream.available(); 
     bufferSize = Math.min(bytesAvailable, maxBufferSize); 
     buffer = new byte[bufferSize]; 
     // Read file 
     bytesRead = fileInputStream.read(buffer, 0, bufferSize); 

     while (bytesRead > 0) 
     { 
     outputStream.write(buffer, 0, bufferSize);   
     bytesAvailable = fileInputStream.available(); 
     bufferSize = Math.min(bytesAvailable, maxBufferSize); 
     bytesRead = fileInputStream.read(buffer, 0, bufferSize); 
     } 

     outputStream.writeBytes(lineEnd); 
     outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); 

     Log.d("posttemplate", "connection outputstream size is " + outputStream.size()); 

     // finished with POST request body 


    // Responses from the server (code and message) 
     serverResponseCode = conn.getResponseCode(); 
     serverResponseMessage = conn.getResponseMessage(); 

     Log.d("posttemplate", "server response code "+ serverResponseCode); 
     Log.d("posttemplate", "server response message "+ serverResponseMessage); 

     fileInputStream.close(); 
     conn.disconnect(); 
     outputStream.flush(); 
     outputStream.close(); 


    } catch (MalformedURLException e) 
    { 
     Log.d("posttemplate", "malformed url", e); 
     //TODO: catch exception; 
    } catch (IOException e) 
    { 
     Log.d("posttemplate", "ioexception", e); 
     //TODO: catch exception 
    }   

} 

दुर्भाग्य से, outputStream.close() पर IOException के साथ अपने ऐप्लिकेशन क्रैश, और मैं क्यों पता नहीं है:

03-16 13:56:51.035: D/posttemplate(6479): java.io.IOException: unexpected end of stream 
03-16 13:56:51.035: D/posttemplate(6479): at org.apache.harmony.luni.internal.net.www.protocol.http.FixedLengthOutputStream.close(FixedLengthOutputStream.java:57) 
03-16 13:56:51.035: D/posttemplate(6479): at java.io.FilterOutputStream.close(FilterOutputStream.java:66) 
03-16 13:56:51.035: D/posttemplate(6479): at com.futubra.api.impl.PostTemplate.createImagePostWithToken(PostTemplate.java:282) 
03-16 13:56:51.035: D/posttemplate(6479): at com.futubra.FutubraNewPostActivity.createPost(FutubraNewPostActivity.java:128) 
03-16 13:56:51.035: D/posttemplate(6479): at com.futubra.FutubraNewPostActivity_.access$2(FutubraNewPostActivity_.java:1) 
03-16 13:56:51.035: D/posttemplate(6479): at com.futubra.FutubraNewPostActivity_$5.run(FutubraNewPostActivity_.java:141) 
03-16 13:56:51.035: D/posttemplate(6479): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
03-16 13:56:51.035: D/posttemplate(6479): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
03-16 13:56:51.035: D/posttemplate(6479): at java.lang.Thread.run(Thread.java:1019) 

उत्तर

1

आपकी जानकारी के लिए, अपने कोड काम करना चाहिए HTTP यूआरएल कनेक्शन के साथ ठीक है, लेकिन एचटीटीपीएस मेमोरी त्रुटि से बाहर हो जाएगा क्योंकि एंड्रॉइड 2.3.4 (मेरे टैबलेट पर सत्यापित) में HttpsURLConnectionImpl.java में एक बग है, और यह बग एंड्रॉइड 4.1 में तय किया गया है (मैंने स्रोत की जांच की है कोड)।

+0

तुम मुझे इस बग है कि आप का उल्लेख को इंगित किया जा सका के रूप में स्ट्रिंग की बाइट लंबाई इस्तेमाल करना चाहिए? मैं जिंजरब्रेड पर HttpsUrlConnection का उपयोग कर एक ही मुद्दे में चल रहा प्रतीत होता है। – HungryTux

2

HTTP शीर्षलेख शरीर का हिस्सा नहीं है, इसलिए उन्हें शरीर की लंबाई के लिए जिम्मेदार न करें।

stringForLength += "Content-Type: multipart/form-data;boundary=" + boundary; 

उपर्युक्त रेखा को हटा दें, इसलिए आप सामग्री की लंबाई सही होगी।

0
int totalLength = stringForLength.length() + (int)file.length(); 

आपका उपरोक्त कोड गलत है।

आप निम्न

int totalLength = stringForLength.getBytes().length + (int)file.length(); 
संबंधित मुद्दे