Java 在Android中发送mulipart/form数据请求
我目前正在创建一个Android应用程序,但遇到了一个问题。 我用Java和Jersey创建了后端部分(托管在服务器上) 我的所有web服务都是POST并返回JSON字符串,几乎所有这些服务都只需要字符串,但其中一些服务还需要接收文件Java 在Android中发送mulipart/form数据请求,java,android,rest,jersey,multipartform-data,Java,Android,Rest,Jersey,Multipartform Data,我目前正在创建一个Android应用程序,但遇到了一个问题。 我用Java和Jersey创建了后端部分(托管在服务器上) 我的所有web服务都是POST并返回JSON字符串,几乎所有这些服务都只需要字符串,但其中一些服务还需要接收文件 当我用Google Postman调用web服务时,一切都正常 当我将来自Android项目的POST请求发送到我(为另一个项目)创建的php文件时,它也可以正常工作 但当我尝试向我的web服务发送请求时,启动Android应用程序时会出错。根据内容类型,响应
- 当我用Google Postman调用web服务时,一切都正常
- 当我将来自Android项目的POST请求发送到我(为另一个项目)创建的php文件时,它也可以正常工作
@POST
@Path("/login")
@Consumes("multipart/form-data")
public String getLogin(@FormDataParam("mail") String mail,
@FormDataParam("pwd") String pwd){ ...
这就是我的Android代码
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod(p.getMethod());
con.setRequestProperty("Content-type", "multipart/form-data");
提前感谢。尝试将两侧的
内容类型设置为application/json
。也就是说,如果要向服务器发送JSON字符串。如果要发送的文件是文本文件,请使用application/text
。否则,请查找有关不同文件格式的正确内容类型的信息。如果您不知道自己在做什么,尝试格式化多部分请求并不是一项简单的任务。您可以查看示例格式和一些说明的详细信息
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
当您发出请求时,主体(和内容类型头)应该是这样的。我制作了简单的助手类,它适用于简单的字符串和文件案例。我没花太长时间就完成了,而且我还没有进行过战斗测试,但它适用于简单的用例。就个人而言,我可能会做一些重构,但这会给你一个起点
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;
public class MultipartHelper {
public String contentType;
public String boundary;
public HttpURLConnection connection;
private final List<FilePart> fileParts = new ArrayList<>();
private final List<StringPart> stringParts = new ArrayList<>();
public MultipartHelper(HttpURLConnection connection) throws IOException {
this(connection, "multipart/form-data");
}
public MultipartHelper(HttpURLConnection connection, String contentType) throws IOException {
this.boundary = String.valueOf(System.currentTimeMillis());
this.connection = connection;
contentType = contentType == null? "multipart/form-data": contentType;
contentType += "; boundary=" + boundary;
connection.setRequestProperty("Content-Type", contentType);
}
public void addStringPart(String data, String name) {
stringParts.add(new StringPart(data, name));
}
public void addFilePart(File file, String contentType, String name) {
if (contentType == null) {
contentType = "application/octet-stream";
}
fileParts.add(new FilePart(file, contentType, name));
}
public void makeRequest() {
Writer writer = null;
try {
OutputStream out = connection.getOutputStream();
writer = new BufferedWriter(new OutputStreamWriter(out));
for (StringPart sp: stringParts) {
writer.write("--" + boundary + "\r\n");
writer.write("Content-Disposition: form-data; name=" + sp.name + "\r\n");
writer.write("Content-Type: text/plain\r\n\r\n");
writer.write(sp.data + "\r\n");
}
writer.flush();
InputStream in = null;
for (FilePart fp: fileParts) {
writer.write("--" + boundary + "\r\n");
writer.write("Content-Disposition: form-data; name="
+ fp.name + "; filename=" + fp.file.getName() + "\r\n");
writer.write("Content-Type: " + fp.contentType + "\r\n\r\n");
writer.flush();
in = new FileInputStream(fp.file);
int count;
byte[] buffer = new byte[2048];
while ((count = in.read(buffer)) != -1) {
out.write(buffer, 0, count);
}
out.flush();
writer.write("\r\n");
writer.flush();
in.close();
}
writer.write("--" + boundary + "--\r\r");
writer.flush();
out.close();
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
class StringPart {
String data;
String name;
public StringPart(String data, String name) {
this.data = data;
this.name = name;
}
}
class FilePart {
File file;
String name;
String contentType;
public FilePart(File file, String contentType, String name) {
this.file = file;
this.name = name;
this.contentType = contentType;
}
}
}
但就我个人而言,我会选择一个已经具备此功能的库。例如,它具有多部分支持。它是一个非常流行的rest客户端库。这里有一个例子
您首先需要依赖关系
马文
首先,您需要客户端服务的接口
import retrofit.http.Multipart;
import retrofit.http.POST;
import retrofit.http.Part;
import retrofit.mime.TypedFile;
import retrofit.mime.TypedString;
public interface UploadService {
@Multipart
@POST("/upload")
retrofit.client.Response upload(@Part("image") TypedFile image,
@Part("string1") TypedString string1);
}
然后像这样提出请求
RestAdapter adapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint("http://localhost:8080/api")
.build();
UploadService service = adapter.create(UploadService.class);
TypedFile file = new TypedFile("image/png", new File("stackoverflow.png"));
TypedString str = new TypedString("Hello World");
retrofit.client.Response response = service.upload(file, str);
感谢您的回答,但是,我对服务器进行了编程,以便我期望作为输入的值是一个键和值列表。与GET请求中完全相同,在GET请求中添加(键、值)对。我的问题是如何将这种类型的数据发送到Java服务器
compile 'com.squareup.retrofit:retrofit:1.9.0'
import retrofit.http.Multipart;
import retrofit.http.POST;
import retrofit.http.Part;
import retrofit.mime.TypedFile;
import retrofit.mime.TypedString;
public interface UploadService {
@Multipart
@POST("/upload")
retrofit.client.Response upload(@Part("image") TypedFile image,
@Part("string1") TypedString string1);
}
RestAdapter adapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint("http://localhost:8080/api")
.build();
UploadService service = adapter.create(UploadService.class);
TypedFile file = new TypedFile("image/png", new File("stackoverflow.png"));
TypedString str = new TypedString("Hello World");
retrofit.client.Response response = service.upload(file, str);