我想将一些文件上传到 HTTP 服务器。基本上我需要的是某种带有一些参数和文件的对服务器的 POST 请求。我已经看到了仅上传文件的示例,但没有找到如何传递其他参数。
这样做的最简单和免费的解决方案是什么?有人有我可以研究的文件上传示例吗?我已经在谷歌上搜索了几个小时,但是(也许这只是其中的一天)找不到我需要的确切内容。最好的解决方案是不涉及任何第三方类或库的东西。
我想将一些文件上传到 HTTP 服务器。基本上我需要的是某种带有一些参数和文件的对服务器的 POST 请求。我已经看到了仅上传文件的示例,但没有找到如何传递其他参数。
这样做的最简单和免费的解决方案是什么?有人有我可以研究的文件上传示例吗?我已经在谷歌上搜索了几个小时,但是(也许这只是其中的一天)找不到我需要的确切内容。最好的解决方案是不涉及任何第三方类或库的东西。
您通常会java.net.URLConnection
用来触发 HTTP 请求。您通常还会multipart/form-data
对混合的 POST 内容(二进制和字符数据)使用编码。单击链接,它包含信息和如何编写multipart/form-data
请求正文的示例。该规范在RFC2388中有更详细的描述。
这是一个启动示例:
String url = "http://example.com/upload";
String charset = "UTF-8";
String param = "value";
File textFile = new File("/path/to/file.txt");
File binaryFile = new File("/path/to/file.bin");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
) {
// Send normal param.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF).append(param).append(CRLF).flush();
// Send text file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); // Text file itself must be saved in this charset!
writer.append(CRLF).flush();
Files.copy(textFile.toPath(), output);
output.flush(); // Important before continuing with writer!
writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.
// Send binary file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(binaryFile.toPath(), output);
output.flush(); // Important before continuing with writer!
writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF).flush();
}
// Request is lazily fired whenever you need to obtain information about response.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println(responseCode); // Should be 200
当您使用 Apache Commons HttpComponents Client 之类的 3rd 方库时,此代码不那么冗长。
Apache Commons FileUpload正如一些错误的建议在这里只对服务器端感兴趣。您不能在客户端使用也不需要它。
以下是使用Apache HttpClient的方法(此解决方案适用于那些不介意使用 3rd 方库的人):
HttpEntity entity = MultipartEntityBuilder.create()
.addPart("file", new FileBody(file))
.build();
HttpPost request = new HttpPost(url);
request.setEntity(entity);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);
单击链接获取示例文件上传 clint java with apache HttpComponents
和图书馆下载链接
https://hc.apache.org/downloads.cgi
使用 4.5.3.zip 它在我的代码中运行良好
和我的工作代码..
import java.io.File;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class ClientMultipartFormPost {
public static void main(String[] args) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost("http://localhost:8080/MyWebSite1/UploadDownloadFileServlet");
FileBody bin = new FileBody(new File("E:\\meter.jpg"));
StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);
HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("bin", bin)
.addPart("comment", comment)
.build();
httppost.setEntity(reqEntity);
System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}
以下是使用 Java 11 的 java.net.http 包的方法:
var fileA = new File("a.pdf");
var fileB = new File("b.pdf");
var mimeMultipartData = MimeMultipartData.newBuilder()
.withCharset(StandardCharsets.UTF_8)
.addFile("file1", fileA.toPath(), Files.probeContentType(fileA.toPath()))
.addFile("file2", fileB.toPath(), Files.probeContentType(fileB.toPath()))
.build();
var request = HttpRequest.newBuilder()
.header("Content-Type", mimeMultipartData.getContentType())
.POST(mimeMultipartData.getBodyPublisher())
.uri(URI.create("http://somehost/upload"))
.build();
var httpClient = HttpClient.newBuilder().build();
var response = httpClient.send(request, BodyHandlers.ofString());
使用以下 MimeMultipartData:
public class MimeMultipartData {
public static class Builder {
private String boundary;
private Charset charset = StandardCharsets.UTF_8;
private List<MimedFile> files = new ArrayList<MimedFile>();
private Map<String, String> texts = new LinkedHashMap<>();
private Builder() {
this.boundary = new BigInteger(128, new Random()).toString();
}
public Builder withCharset(Charset charset) {
this.charset = charset;
return this;
}
public Builder withBoundary(String boundary) {
this.boundary = boundary;
return this;
}
public Builder addFile(String name, Path path, String mimeType) {
this.files.add(new MimedFile(name, path, mimeType));
return this;
}
public Builder addText(String name, String text) {
texts.put(name, text);
return this;
}
public MimeMultipartData build() throws IOException {
MimeMultipartData mimeMultipartData = new MimeMultipartData();
mimeMultipartData.boundary = boundary;
var newline = "\r\n".getBytes(charset);
var byteArrayOutputStream = new ByteArrayOutputStream();
for (var f : files) {
byteArrayOutputStream.write(("--" + boundary).getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(("Content-Disposition: form-data; name=\"" + f.name + "\"; filename=\"" + f.path.getFileName() + "\"").getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(("Content-Type: " + f.mimeType).getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(Files.readAllBytes(f.path));
byteArrayOutputStream.write(newline);
}
for (var entry: texts.entrySet()) {
byteArrayOutputStream.write(("--" + boundary).getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"").getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(entry.getValue().getBytes(charset));
byteArrayOutputStream.write(newline);
}
byteArrayOutputStream.write(("--" + boundary + "--").getBytes(charset));
mimeMultipartData.bodyPublisher = BodyPublishers.ofByteArray(byteArrayOutputStream.toByteArray());
return mimeMultipartData;
}
public class MimedFile {
public final String name;
public final Path path;
public final String mimeType;
public MimedFile(String name, Path path, String mimeType) {
this.name = name;
this.path = path;
this.mimeType = mimeType;
}
}
}
private String boundary;
private BodyPublisher bodyPublisher;
private MimeMultipartData() {
}
public static Builder newBuilder() {
return new Builder();
}
public BodyPublisher getBodyPublisher() throws IOException {
return bodyPublisher;
}
public String getContentType() {
return "multipart/form-data; boundary=" + boundary;
}
}
public static String simSearchByImgURL(int catid ,String imgurl) throws IOException{
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String result =null;
try {
HttpPost httppost = new HttpPost("http://api0.visualsearchapi.com:8084/vsearchtech/api/v1.0/apisim_search");
StringBody catidBody = new StringBody(catid+"" , ContentType.TEXT_PLAIN);
StringBody keyBody = new StringBody(APPKEY , ContentType.TEXT_PLAIN);
StringBody langBody = new StringBody(LANG , ContentType.TEXT_PLAIN);
StringBody fmtBody = new StringBody(FMT , ContentType.TEXT_PLAIN);
StringBody imgurlBody = new StringBody(imgurl , ContentType.TEXT_PLAIN);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addPart("apikey", keyBody).addPart("catid", catidBody)
.addPart("lang", langBody)
.addPart("fmt", fmtBody)
.addPart("imgurl", imgurlBody);
HttpEntity reqEntity = builder.build();
httppost.setEntity(reqEntity);
response = httpClient.execute(httppost);
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
// result = ConvertStreamToString(resEntity.getContent(), "UTF-8");
String charset = "UTF-8";
String content=EntityUtils.toString(response.getEntity(), charset);
System.out.println(content);
}
EntityUtils.consume(resEntity);
}catch(Exception e){
e.printStackTrace();
}finally {
response.close();
httpClient.close();
}
return result;
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
return;
}
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(MAX_MEMORY_SIZE);
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
String uploadFolder = getServletContext().getRealPath("")
+ File.separator + DATA_DIRECTORY;//DATA_DIRECTORY is directory where you upload this file on the server
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(MAX_REQUEST_SIZE);//MAX_REQUEST_SIZE is the size which size you prefer
并在html中使用<form enctype="multipart/form-data">
和使用<input type="file">