(解决 - 以下见注释)HttpURLConnection的失败在Android
我有一个实现多文件上传的类。该代码适用于除Android以外的每个我尝试过的Java客户端,并且这是我的Android应用中唯一的HTTP请求代码,与我的后端服务无关。
连接responseCode是“-1”,所以在这里进行一些非常讨厌的事情。 Apache访问或错误日志中没有任何条目出现,看起来好像请求永远不会脱离android平台。代码正好通过连接写入,但挂在连接读取上,超时然后返回。行为对于真实的手机和模拟器是相同的。
有没有人知道在Android中发布多部分文件时需要注意什么问题?
我包括下面的类(轻微的卫生MODS的制作),所以你可以看到我到
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class GeoPictureUploader
{
static String serviceDomain = "http://staging.abaqus.net";
static String postUrl = serviceDomain + "/geo/upl/wupload/pictures";
static String CRLF = "\r\n";
static String twoHyphens = "--";
static String boundary = "*****mgd*****";
private String pictureFileName = null;
private String name = null;
private String password = null;
private DataOutputStream dataStream = null;
enum ReturnCode { noPicture, unknown, http201, http400, http401, http403, http404, http500};
public GeoPictureUploader(String name, String password)
{
this.name = name;
this.password = password;
}
public static void setServiceDomain(String domainName)
{
serviceDomain = domainName;
}
public static String getServiceDomain()
{
return serviceDomain;
}
public ReturnCode uploadPicture(String pictureFileName)
{
this.pictureFileName = pictureFileName;
File uploadFile = new File(pictureFileName);
if (uploadFile.exists())
try
{
FileInputStream fileInputStream = new FileInputStream(uploadFile);
URL connectURL = new URL(postUrl);
HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("User-Agent", "myGeodiary-V1");
conn.setRequestProperty("Connection","Keep-Alive");
conn.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);
conn.connect();
dataStream = new DataOutputStream(conn.getOutputStream());
writeFormField("login", name);
writeFormField("password", password);
writeFileField("photo1", pictureFileName, "image/jpg", fileInputStream);
// final closing boundary line
dataStream.writeBytes(twoHyphens + boundary + twoHyphens + CRLF);
fileInputStream.close();
dataStream.flush();
dataStream.close();
dataStream = null;
String response = getResponse(conn);
int responseCode = conn.getResponseCode();
if (response.contains("uploaded successfully"))
return ReturnCode.http201;
else
// for now assume bad name/password
return ReturnCode.http401;
}
catch (MalformedURLException mue) {
// Log.e(Tag, "error: " + mue.getMessage(), mue);
System.out.println("GeoPictureUploader.uploadPicture: Malformed URL: " + mue.getMessage());
return ReturnCode.http400;
}
catch (IOException ioe) {
// Log.e(Tag, "error: " + ioe.getMessage(), ioe);
System.out.println("GeoPictureUploader.uploadPicture: IOE: " + ioe.getMessage());
return ReturnCode.http500;
}
catch (Exception e) {
// Log.e(Tag, "error: " + ioe.getMessage(), ioe);
System.out.println("GeoPictureUploader.uploadPicture: unknown: " + e.getMessage());
return ReturnCode.unknown;
}
else
{
return ReturnCode.noPicture;
}
}
/**
* @param conn
* @return
*/
private String getResponse(HttpURLConnection conn)
{
try
{
DataInputStream dis = new DataInputStream(conn.getInputStream());
byte [] data = new byte[1024];
int len = dis.read(data, 0, 1024);
dis.close();
int responseCode = conn.getResponseCode();
if (len > 0)
return new String(data, 0, len);
else
return "";
}
catch(Exception e)
{
System.out.println("GeoPictureUploader: biffed it getting HTTPResponse");
//Log.e(TAG, "GeoPictureUploader: biffed it getting HTTPResponse");
return "";
}
}
/**
* this mode of reading response no good either
*/
private String getResponseOrig(HttpURLConnection conn)
{
InputStream is = null;
try
{
is = conn.getInputStream();
// scoop up the reply from the server
int ch;
StringBuffer sb = new StringBuffer();
while((ch = is.read()) != -1) {
sb.append((char)ch);
}
return sb.toString(); // TODO Auto-generated method stub
}
catch(Exception e)
{
System.out.println("GeoPictureUploader: biffed it getting HTTPResponse");
//Log.e(TAG, "GeoPictureUploader: biffed it getting HTTPResponse");
}
finally
{
try {
if (is != null)
is.close();
} catch (Exception e) {}
}
return "";
}
/**
* write one form field to dataSream
* @param fieldName
* @param fieldValue
*/
private void writeFormField(String fieldName, String fieldValue)
{
try
{
dataStream.writeBytes(twoHyphens + boundary + CRLF);
dataStream.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\"" + CRLF);
dataStream.writeBytes(CRLF);
dataStream.writeBytes(fieldValue);
dataStream.writeBytes(CRLF);
}
catch(Exception e)
{
System.out.println("GeoPictureUploader.writeFormField: got: " + e.getMessage());
//Log.e(TAG, "GeoPictureUploader.writeFormField: got: " + e.getMessage());
}
}
/**
* write one file field to dataSream
* @param fieldName - name of file field
* @param fieldValue - file name
* @param type - mime type
* @param fileInputStream - stream of bytes that get sent up
*/
private void writeFileField(
String fieldName,
String fieldValue,
String type,
FileInputStream fis)
{
try
{
// opening boundary line
dataStream.writeBytes(twoHyphens + boundary + CRLF);
dataStream.writeBytes("Content-Disposition: form-data; name=\""
+ fieldName
+ "\";filename=\""
+ fieldValue
+ "\""
+ CRLF);
dataStream.writeBytes("Content-Type: " + type + CRLF);
dataStream.writeBytes(CRLF);
// create a buffer of maximum size
int bytesAvailable = fis.available();
int maxBufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];
// read file and write it into form...
int bytesRead = fis.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
dataStream.write(buffer, 0, bufferSize);
bytesAvailable = fis.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fis.read(buffer, 0, bufferSize);
}
// closing CRLF
dataStream.writeBytes(CRLF);
}
catch(Exception e)
{
System.out.println("GeoPictureUploader.writeFormField: got: " + e.getMessage());
//Log.e(TAG, "GeoPictureUploader.writeFormField: got: " + e.getMessage());
}
}
/**
* @param args
*/
public static void main(String[] args)
{
if (args.length >= 0)
{
GeoPictureUploader gpu = new GeoPictureUploader("john", "notmyrealpassword");
String picName = args[0];
ReturnCode rc = gpu.uploadPicture(picName);
System.out.printf("done");
}
}
}
几个小时的调试后,它原来是我们的路由器中的错误,由于某种原因或其他挂在出站往返回到我们分期服务器当消息超过几个k字节时。我一直在开发使用无线网络连接的手机,当然仿真器也使用网络。一旦我们瞄准了我们的生产服务器,它就立即开始工Cellular也很好。 – jottos 2009-07-14 10:04:30
大家请随意使用这个Android multipart/form-data类。它像一个冠军。并且很容易推广到通用的多部分/表单数据类。 对代码的清理提示 - 您可以删除getResponse()方法,转而使用 HttpURLConnection方法conn.getResponseMethod(),当然也可以使用conn.getResponseCode()来获取正确的http服务器代码 – jottos 2009-07-14 10:05:27