[英]Problems when sending XML data from HTTP Java client to a servlet with HttpURLConnection
我有一个独立的Java客户端使用httpURLconnection类将xml数据发送到http servlet,但是数据以不可打印的字符格式显示。
为了进行模拟,我一直在尝试发送简单的字符串,但是它仍然以不可打印的格式出现。
我已经编写了以下客户端代码来与Servlet进行通信,
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.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
public class HttpClient implements IClient {
private static IClient client = null;
private HttpURLConnection httpConn = null;
private OutputStream output = null;
private InputStream input = null;
private OutputStreamWriter out = null;
private HttpClient() {
}
public static IClient getHttpClient() {
if (client == null) {
client = new HttpClient();
}
return client;
}
@Override
public void connect(String urlString) throws IOException {
URL url = new URL(urlString);
httpConn = (HttpURLConnection) url.openConnection();
initConnection();
httpConn.connect();
output = httpConn.getOutputStream();
input = httpConn.getInputStream();
System.out.println("Connection Response:" + httpConn.getResponseCode());
}
@Override
public void sendFile(File file) throws IOException {
// BufferedOutputStream bos = new BufferedOutputStream(output);
// InputStream fis = new FileInputStream(file);
// int bytesRead = 0;
// byte[] buffer = new byte[8192];
// while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
// bos.write(buffer, 0, bytesRead);
// System.out.println("write:"+buffer);
// }
// bos.close();
// fis.close();
OutputStreamWriter out = new OutputStreamWriter(output, "UTF-16");
out.write("test me");
}
@Override
public boolean isConnected() {
return httpConn != null ? true : false;
}
@Override
public void close() {
httpConn.disconnect();
}
private void initConnection() throws ProtocolException {
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
httpConn.setUseCaches(false);
httpConn.setRequestProperty("Content-Type",
"text/xml; charset=\"UTF-16\"");
httpConn.setRequestProperty("Connection", "Keep-Alive");
}
private static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
System.out.println("\nDEBUG: FileInputStream is " + file);
// Get the size of the file
long length = file.length();
System.out.println("DEBUG: Length of " + file + " is " + length + "\n");
/*
* You cannot create an array using a long type. It needs to be an int
* type. Before converting to an int type, check to ensure that file is
* not loarger than Integer.MAX_VALUE;
*/
if (length > Integer.MAX_VALUE) {
System.out.println("File is too large to process");
return null;
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int) length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while ((offset < bytes.length)
&& ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "
+ file.getName());
}
return bytes;
}
}
并在下面给出了servlet代码,
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class XMLServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("=========inside doPost=========");
// BufferedInputStream bis = new BufferedInputStream(req.getInputStream());
// OutputStream fos = new FileOutputStream("test.xml");
// int bytesRead = 0;
// byte[] buffer = new byte[8192];
// while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) {
// System.out.println("read:"+buffer);
// fos.write(buffer, 0, bytesRead);
// }
// fos.close();
// bis.close();
//
req.setCharacterEncoding("UTF-16");
InputStreamReader isr = new InputStreamReader(req.getInputStream(),"UTF-16");
char[] data = new char[10];
isr.read(data);
System.out.println(data);
for (char c : data) {
System.out.println(c);
}
}
}
请任何帮助我摆脱这个问题。
我认为您太复杂了。 我只写了类似的东西,它可以接收任何文件并将其通过HTTP传输到servlet。 只需记住:所有数据都是二进制(包括文本文件)-周期。 由给定的应用程序来解释该二进制数据。 例如,notepad.exe仅读取二进制数据集并尝试使用ASCII标准对其进行格式化。 因此,只需使用原始流读取文件,将连接的mime类型设置为application / octet-stream,然后通过“ PUT”方法将其发送即可。 Servlet代码应使用请求中的原始InputStream读取文件,并在其空间中创建相应的文件。
从客户端代码:
URL url = new URL(urlString);
HttpURLConnection cnx = (HttpURLConnection)url.openConnection();
cnx.setRequestMethod("PUT");
cnx.setRequestProperty("Content-Type", "application/octet-stream");
// optional request property
cnx.setRequestProperty("filename", filename);
cnx.setDoOutput(true);
cnx.connect();
BufferedInputStream fileIn =
new BufferedInputStream(new FileInputStream(fileName), BUFFER_SIZE);
BufferedOutputStream out =
new BufferedOutputStream(cnx.getOutputStream(), BUFFER_SIZE);
byte[] bytes = new byte[BUFFER_SIZE];
int bytesRead;
while((bytesRead = fileIn.read(bytes)) != -1){
out.write(bytes, 0, bytesRead);
}
而已。
现在是servlet代码。
public void doPut(HttpServletRequest request, HttpServletResponse response){
String filename = (String)request.getHeader("filename");
StringBuilder fullPath = new StringBuilder(100);
ServletContext ctxt = getServletContext();
fullPath.append(ctxt.getRealPath(""))
.append("uploads\\").append(filename);
File f = new File(fullPath.toString());
f.createNewFile();
InputStream in = request.getInputStream();
BufferedOutputStream fileOut =
new BufferedOutputStream(new FileOutputStream(f));
byte[] bytes = new byte[BUFFER_SIZE];
int bytesRead;
while((bytesRead = in.read(bytes)) != -1){
fileOut.write(bytes, 0, bytesRead);
}
fileOut.flush();
fileOut.close();
response.setStatus(HttpServletResponse.SC_CREATED);
}
使用http方法将文件上传到服务器的方式主要有两种:
使用PUT
方法上传文件。 这使您可以一次将一个文件放到服务器上。 PUT方法易于实现,但是您不能使用PUT
方法从html表单上载文件(例如,在Web浏览器中上载表单)。
使用POST
方法上传文件。 这比较复杂,但是大多数网站都使用它来将文件上传到服务器上。 您可以针对每个请求上传多个文件。 这就是我要谈的。
注意: GET
不用于文件上传,除非您以某种方式对其进行编码。
使用URLConnection
上传文件不是直接的,需要您以“ 多部分形式 ”准备数据。 当然,您不应该自己做。 有许多库可以为您解决这个问题,例如HttpClient 。 如果您真的想使用URLConnection
,我将参考前面的问题“ 如何使用java.net.URLConnection来触发和处理HTTP请求 ”
以下是使用HttpClient上传文件的代码。 它从HttpClient示例代码简化。
import java.io.File;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpMethodParams;
public class MultipartFileUploadApp {
public static void main(String[] args) {
String targetURL = "http://localhost:8080/yourserver/upload";
File targetFile = new File("/path/to/your/file.txt");
PostMethod filePost = new PostMethod(targetURL);
filePost.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
try {
System.out.println("Uploading " + targetFile.getName() + " to " + targetURL);
// add more parts you want to upload multiple files.
Part[] parts = {new FilePart(targetFile.getName(), targetFile)};
filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
int status = client.executeMethod(filePost);
if (status == HttpStatus.SC_OK) {
System.out.println("Upload complete, response=" + filePost.getResponseBodyAsString());
} else {
System.out.println("Upload failed, response=" + HttpStatus.getStatusText(status));
}
} catch (Exception ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
filePost.releaseConnection();
}
}
}
对于服务器端,您必须解析多部分表单请求。 当然,存在可以为您执行此操作的库。 这是我正在使用的片段
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class CommonsFileUploadServlet extends HttpServlet {
private static final String TMP_DIR_PATH = "c:\\tmp";
private File tmpDir;
private static final String DESTINATION_DIR_PATH = "c:\\tmp\\files";
private File destinationDir;
public void init(ServletConfig config) throws ServletException {
super.init(config);
tmpDir = new File(TMP_DIR_PATH);
if (!tmpDir.isDirectory()) {
throw new ServletException(TMP_DIR_PATH + " is not a directory");
}
//String realPath = getServletContext().getRealPath(DESTINATION_DIR_PATH);
destinationDir = new File(DESTINATION_DIR_PATH);
if (!destinationDir.isDirectory()) {
throw new ServletException(DESTINATION_DIR_PATH + " is not a directory");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
out.println("<h1>Servlet File Upload Example using Commons File Upload</h1>");
out.println();
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
/*
*Set the size threshold, above which content will be stored on disk.
*/
fileItemFactory.setSizeThreshold(1 * 1024 * 1024); //1 MB
/*
* Set the temporary directory to store the uploaded files of size above threshold.
*/
fileItemFactory.setRepository(tmpDir);
ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
try {
/*
* Parse the request
*/
List items = uploadHandler.parseRequest(request);
out.println("Count : " + items.size());
Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
/*
* Handle Form Fields.
*/
if (item.isFormField()) {
out.println("Field = " + item.getFieldName() + ", Value = " + item.getString());
} else {
//Handle Uploaded files.
out.println("Field Name = " + item.getFieldName()
+ ", File Name = " + item.getName()
+ ", Content type = " + item.getContentType()
+ ", File Size = " + item.getSize());
/*
* Write file to the ultimate location.
*/
File file = new File(destinationDir, item.getName());
item.write(file);
}
}
out.close();
} catch (FileUploadException ex) {
log("Error encountered while parsing the request", ex);
} catch (Exception ex) {
log("Error encountered while uploading file", ex);
}
}
}
我有一个独立的Java客户端使用httpURLconnection类将xml数据发送到http servlet,但是数据以不可打印的字符格式显示。
我能理解 您以UTF-16的形式发送数据,但是XML文件本身可能未保存在UTF-16中。 您需要使用与保存XML文件相同的字符编码。通常为UTF-8。
为了进行模拟,我一直在尝试发送简单的字符串,但是它仍然以不可打印的格式出现。
我不明白 它应该可以像您在代码中那样很好地工作。 可能您没有正确测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.