我正在尝试使用Java HTTP POST请求将图像发送到网站。
我正在使用此处使用的基本代码Upload files from Java client to a HTTP server:
这是我的修改:
String urlToConnect = "http://localhost:9000/upload";
File fileToUpload = new File("C:\\Users\\joao\\Pictures\\bla.jpg");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
URLConnection connection = new URL(urlToConnect).openConnection();
connection.setDoOutput(true); // This sets request method to POST.
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream()));
writer.println("--" + boundary);
writer.println("Content-Disposition: form-data; name=\"picture\"; filename=\"bla.jpg\"");
writer.println("Content-Type: image/jpeg");
writer.println();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileToUpload)));
for (String line; (line = reader.readLine()) != null;) {
writer.println(line);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
}
writer.println("--" + boundary + "--");
} finally {
if (writer != null) writer.close();
}
// Connection is lazily executed whenever you request any status.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println(responseCode); // Should be 200
我最终获得了200个响应代码,但是图像是错误的,就像随机颜色一样,这让我觉得它是字符编码中的错误。我尝试使用原始示例中的UTF-8,但这只会创建一个损坏的图像。
我也100%确定它不是服务器端问题,因为我可以使用其他客户端,例如Advanced Rest Client / Postman,他们可以发送没有问题的图像。
你能帮我查明错误吗?谢谢。
答案 0 :(得分:18)
import java.io.File;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
public class PostFile {
public static void main(String[] args) throws Exception {
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpPost httppost = new HttpPost("http://localhost:9000/upload");
File file = new File("C:\\Users\\joao\\Pictures\\bla.jpg"");
MultipartEntity mpEntity = new MultipartEntity();
ContentBody cbFile = new FileBody(file, "image/jpeg");
mpEntity.addPart("userfile", cbFile);
httppost.setEntity(mpEntity);
System.out.println("executing request " + httppost.getRequestLine());
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
System.out.println(response.getStatusLine());
if (resEntity != null) {
System.out.println(EntityUtils.toString(resEntity));
}
if (resEntity != null) {
resEntity.consumeContent();
}
httpclient.getConnectionManager().shutdown();
}
}
使用HttpClient计算出此代码。除了以自定义方式处理某些内容之外,使用除了从头开始处理之外的稳定库总是更好。
答案 1 :(得分:3)
Reader / Writer类用于处理文本数据,而图像是二进制的。您需要将文件解释为二进制文件:
FileChannel in = new FileInputStream(fileToUpload).getChannel();
WritableByteChannel out = Channels.newChannel(connection.getOutputStream());
in.transferTo(0, fileToUpload.size(), out)
当然,您仍然需要关闭所有已打开的资源。
答案 2 :(得分:2)
试试:
private DefaultHttpClient mHttpClient;
Context context;
public String error = "";
//Contrutor para que metodos possam ser usados fora de uma activity
public HTTPconector(Context context) {
this.context = context;
}
public HTTPconector() {
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
mHttpClient = new DefaultHttpClient(params);
}
public void FileClientPost(String txtUrl, File file){
try
{
error = "";
HttpPost httppost = new HttpPost(txtUrl);
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("Image", new FileBody(file));
httppost.setEntity(multipartEntity);
mHttpClient.execute(httppost, new PhotoUploadResponseHandler());
}
catch (Exception e)
{
Log.e(HTTPconector.class.getName(), e.getLocalizedMessage(), e);
e.getStackTrace();
error = e.getMessage();
}
}
//Verifica se a rede esta disponível
public boolean isNetworkAvailable() {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
// if no network is available networkInfo will be null
// otherwise check if we are connected
if (networkInfo != null && networkInfo.isConnected()) {
return true;
}
return false;
}
public String Get(String txtUrl){
try {
URL url = new URL(txtUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(10000);
con.setConnectTimeout(15000);
con.setRequestMethod("GET");
con.setDoInput(true);
con.connect();
return readStream(con.getInputStream());
} catch (ProtocolException e) {
e.printStackTrace();
return "ERRO: "+e.getMessage();
} catch (IOException e) {
e.printStackTrace();
return "ERRO: "+e.getMessage();
}
}
public String Post(String txtUrl){
File image;
try {
URL url = new URL(txtUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
con.connect();
//con.getOutputStream().write( ("name=" + "aa").getBytes());
return readStream(con.getInputStream());
} catch (ProtocolException e) {
e.printStackTrace();
return "ERRO: "+e.getMessage();
} catch (IOException e) {
e.printStackTrace();
return "ERRO: "+e.getMessage();
}
}
//Usado para fazer conexão com a internet
public String conectar(String u){
String resultServer = "";
try {
URL url = new URL(u);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
resultServer = readStream(con.getInputStream());
} catch (Exception e) {
e.printStackTrace();
resultServer = "ERRO: "+ e.getMessage();
}
Log.i("HTTPMANAGER: ", resultServer);
return resultServer;
}
//Lê o resultado da conexão
private String readStream(InputStream in) {
String serverResult = "";
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
serverResult = reader.toString();
} catch (IOException e) {
e.printStackTrace();
serverResult = "ERRO: "+ e.getMessage();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
serverResult = "ERRO: "+ e.getMessage();
}
}
}
return serverResult;
}
private class PhotoUploadResponseHandler implements ResponseHandler<Object>
{
@Override
public Object handleResponse(HttpResponse response)throws ClientProtocolException, IOException {
HttpEntity r_entity = response.getEntity();
String responseString = EntityUtils.toString(r_entity);
Log.d("UPLOAD", responseString);
return null;
}
}
答案 3 :(得分:1)
今天,我遇到了同样的问题,我写了一个nodejs服务器,仅支持两条路由,即上传和下载图像。
客户端应该是一个Java类,该类通过HTTP POST multipart/form-data标准将图像有效载荷发送到服务器。
如果您想知道为什么HTTP POST multipart/form-data,请在这篇文章中查看Ciro Santilli的回答:What does enctype='multipart/form-data' mean?
幸运的是,我发现了这个很好的示例代码:
它显示了如何在没有任何外部库的情况下手动构建多部分http主体的有效负载,在我看来,只有一点限制是它只能处理一个文件的多主体。
因为我没有HTML页面来嗅探生成的POST负载,所以我使用python来生成它并通过wireshark嗅探它。
Python3代码:
import requests
posturl = 'http://<server>:<port>/<path>'
files = {'image' : open('<file>', 'rb')}
r = requests.post(posturl, files = files)
仅需注意:如果我们使用dict从请求库中定义参数 files ,它将生成mulipart / form-data内容。 http://docs.python-requests.org/en/master/user/advanced/#post-multiple-multipart-encoded-files
Wireshark展示的一切都很清晰,最后我最终将其发送给Java:
HttpURLConnection conn =
(HttpURLConnection) new URL("http://<server>:<port>/<path>")).openConnection();
// some arbitrary text for multitext boundary
// only 7-bit US-ASCII digits max length 70
String boundary_string = "some radom/arbitrary text";
// we want to write out
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.addRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary_string);
// now we write out the multipart to the body
OutputStream conn_out = conn.getOutputStream();
BufferedWriter conn_out_writer = new BufferedWriter(new OutputStreamWriter(conn_out));
// write out multitext body based on w3 standard
// https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
conn_out_writer.write("\r\n--" + boundary_string + "\r\n");
conn_out_writer.write("Content-Disposition: form-data; " +
"name=\"image\"; " +
"filename=\""+ <File class instance>.getName() +"\"" +
"\r\n\r\n");
conn_out_writer.flush();
// payload from the file
FileInputStream file_stream = new FileInputStream(<File class instance>);
// write direct to outputstream instance, because we write now bytes and not strings
int read_bytes;
byte[] buffer = new byte[1024];
while((read_bytes = file_stream.read(buffer)) != -1) {
conn_out.write(buffer, 0, read_bytes);
}
conn_out.flush();
// close multipart body
conn_out_writer.write("\r\n--" + boundary_string + "--\r\n");
conn_out_writer.flush();
// close all the streams
conn_out_writer.close();
conn_out.close();
file_stream.close();
// execute and get response code
conn.getResponseCode();
要获取POST的响应,只需读取通过getInputStream()访问的输入流,并在链接中插入代码即可。