【发布时间】:2014-08-20 10:45:21
【问题描述】:
我已经参考了这个链接Sending files using POST with HttpURLConnection
使用以下代码,我正在尝试将文件发布到本地 PHP 服务器。它总是在我的 PHP 文件中返回文件大小 0
public class FileUpload2 {
String CRLF = "\r\n";
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
new FileUpload2().put("http://localhost/test/test.php");
}
public void put(String targetURL) throws Exception {
String BOUNDRY = "==================================";
HttpURLConnection conn = null;
try {
// These strings are sent in the request body. They provide
// information about the file being uploaded
String contentDisposition = "Content-Disposition: form-data; name=\"userfile\"; filename=\"test.txt\"";
String contentType = "Content-Type: application/octet-stream";
// This is the standard format for a multipart request
StringBuffer requestBody = new StringBuffer();
requestBody.append("--");
requestBody.append(BOUNDRY);
requestBody.append(CRLF);
requestBody.append(contentDisposition);
requestBody.append(CRLF);
requestBody.append(contentType);
requestBody.append(CRLF);
requestBody.append("Content-Transfer-Encoding: binary" + CRLF);
requestBody.append(CRLF);
requestBody.append(new String(getFileBytes("test.txt")));
requestBody.append("--");
requestBody.append(BOUNDRY);
requestBody.append("--");
requestBody.append(CRLF);
// Make a connect to the server
URL url = new URL(targetURL);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + BOUNDRY);
conn.setRequestProperty("Cache-Control", "no-cache");
// Send the body
DataOutputStream dataOS = new DataOutputStream(
conn.getOutputStream());
dataOS.writeBytes(requestBody.toString());
dataOS.flush();
dataOS.close();
// Ensure we got the HTTP 200 response code
int responseCode = conn.getResponseCode();
if (responseCode != 200) {
throw new Exception(String.format(
"Received the response code %d from the URL %s",
responseCode, url));
}
// Read the response
InputStream is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(bytes)) != -1) {
baos.write(bytes, 0, bytesRead);
}
byte[] bytesReceived = baos.toByteArray();
baos.close();
is.close();
String response = new String(bytesReceived);
System.out.println(response);
// TODO: Do something here to handle the 'response' string
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
public byte[] getFileBytes(String file) throws IOException {
ByteArrayOutputStream ous = null;
InputStream ios = null;
try {
byte[] buffer = new byte[4096];
ous = new ByteArrayOutputStream();
ios = this.getClass().getResourceAsStream(file);
int read = 0;
while ((read = ios.read(buffer)) != -1)
ous.write(buffer, 0, read);
} finally {
try {
if (ous != null)
ous.close();
} catch (IOException e) {
// swallow, since not that important
}
try {
if (ios != null)
ios.close();
} catch (IOException e) {
// swallow, since not that important
}
}
return ous.toByteArray();
}
PHP 文件
<?php
move_uploaded_file($_FILES['userfile']["tmp_name"], "test.txt");
//file_put_contents("test", "asd".$_FILES['userfile']);
print_r($_FILES);
print_r($_REQUEST);
?>
我得到的结果是
Array
(
[userfile] => Array
(
[name] => test.txt
[type] =>
[tmp_name] =>
[error] => 3
[size] => 0
)
)
Array
(
)
提前致谢!
【问题讨论】:
-
为什么要将文本文件转换为字节,然后再转换回字符串?即使你有一个二进制文件,你也不应该只用这些字节创建一个字符串,因为可能有控制字符会破坏你的请求,而是使用 base64 等对字节进行编码。
-
顺便说一句,
[error] => 3不是表示至少有一个错误吗?如果是这样,您可以检查并发布错误。 -
[error] => 3 表示根据 PHP 文档上传的部分文件
-
当然你需要在接收端解码(顺便说一句,这不是加密只是编码)。正如我所说,我建议不要将二进制数据字节写入未编码的字符串,因为这可能会导致不需要的控制字符,如
\0(或 unicode\u0000)。如果您只有文本文件,那么我会将这些文件作为字符串而不是字节数组读取。 -
附带说明:构造函数
String(byte[])将使用JVM 的默认编码将字节转换为字符。如果该编码与用于创建字节数组的编码不匹配,您将无法返回您期望的字符串(它可能在编码重叠的极少数情况下起作用,但不要指望这一点)。因此,您可能希望将字符编码作为参数传递,例如通过使用String(byte[],String)或String(byte[], Charset)。
标签: java http post client-server httpurlconnection