Android 上的 HttpURLConnection 失败
(已解决 - 请参阅下面的评论)
我有一个实现分段文件上传的类。 该代码适用于我尝试过的每个 Java 客户端(Android 除外),并且它是我的 Android 应用程序中唯一不能与我的后端服务很好地配合的 HTTP 请求代码。
连接响应代码是“-1”,所以这里发生了一些非常令人讨厌的事情。 Apache 访问或错误日志中没有显示任何条目,似乎请求从未离开 Android 平台。 代码通过连接写入正确执行,但在连接读取时挂起,超时然后返回。 真实手机和模拟器的行为是相同的。
有谁知道在 Android 中发布多部分文件时需要注意的问题吗?
我包括下面的课程(做了一些小的卫生修改),这样你就可以看到我在做什么
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");
}
}
}
(Solved - see comment below)
I have a class that implements a multipart file upload. The code works on every java client I've tried it on except for Android, and it's the only HTTP request code in my Android app that doesn't play nice with my back end service.
The connection responseCode is "-1" so something pretty nasty is going on here. No entries show up in the Apache access or error logs, it seems as if the request is never making it off of the android platform. The code gets right through the connection writes, but hangs on the connection read, times out and then returns. Behavior is same for real phone and emulator.
Does anyone know of any gotchas one needs to look out for when posting a multipart file in Android?
I'm including the class below (minor hygienic mods made) so you can see what I'm up to
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");
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你设置了互联网权限吗? 在尝试调试帖子之前,我会确保简单的获取(使用 HTTPUrl 获取 google)。
Have you set the internet permission? I would make sure simple Gets (Use the HTTPUrl to fetch google) before trying to debug post.
您好,我已经使用相同的 HttpURLConnection 完成了文件上传。
我能够将最大 25 mb 的文件上传到 Restful 服务。
看看这可能对你有帮助:
链接
HI i have done file uploading using same HttpURLConnection.
i am able to upload files up to 25 mb to restful services.
have a look this might be helpful for you :
link