我在将.zip文件上传到远程服务器时遇到问题,因为上传后文件中缺少某些字节。重新加载文件后,.zip存档无法打开,这使我相信我需要这些字节才能成功执行上传。
我使用multipart / form-data POST请求上传文件。我用来执行此操作的实用程序帮助程序类在以下代码中给出:
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
public class MultipartFormDataUtil {
private final String boundary;
private static final String lineReturn = "\r\n";
private HttpURLConnection conn;
private DataOutputStream dos;
int bytesRead, bytesAvail, bufferSize;
byte[] buffer;
int maxBufferSize = 1*1024*1024;
List<String> response;
public MultipartFormDataUtil(String postUrl, LinkedHashMap<String, String> params, File file) throws IOException {
boundary = "=-=" + System.currentTimeMillis() + "=-=";
URL url = new URL(postUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
dos = new DataOutputStream(conn.getOutputStream());
for (String key : params.keySet()) {
addFormPart(key, params.get(key));
}
addFilePart(file);
finish();
}
private void addFormPart(String name, String value) throws IOException {
dos.writeBytes("--" + boundary + lineReturn);
dos.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"" + lineReturn);
dos.writeBytes("Content-Type: text/plain" + lineReturn + lineReturn);
dos.writeBytes(value + lineReturn);
dos.flush();
}
private void addFilePart(File file) throws IOException {
FileInputStream fileInputStream = new FileInputStream(file);
dos.writeBytes("--" + boundary + lineReturn);
dos.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"" + lineReturn);
dos.writeBytes("Content-Type: " + URLConnection.guessContentTypeFromName(file.getName()) + lineReturn);
dos.writeBytes("Content-Transfer-Encoding: binary" + lineReturn + lineReturn);
bytesAvail = fileInputStream.available();
bufferSize = Math.min(bytesAvail, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvail = fileInputStream.available();
bufferSize = Math.min(bytesAvail, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dos.flush();
dos.writeBytes(lineReturn);
dos.flush();
fileInputStream.close();
}
private void finish() throws IOException {
response = new ArrayList<String>();
dos.writeBytes("--" + boundary + "--" + lineReturn);
dos.flush();
dos.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
response.add(line);
}
reader.close();
conn.disconnect();
}
public List<String> getResponse() {
return response;
}
要在信用到期时给予信用,此实用程序基于Peter's Notes和CodeJava.net的示例。使用以下代码调用此util:
protected static void postFile(String url, LinkedHashMap<String, String> params, File file) throws Exception {
try {
MultipartFormDataUtil multipartRequest = new MultipartFormDataUtil(url, params, file);
List<String> response = multipartRequest.getResponse();
for (String line : response) {
System.out.println(line);
}
} catch (IOException ioe) {
log.warn("There was an error posting the file and form data", ioe);
}
}
在这种情况下,上传网址是一个Amazon S3存储桶,它将其传递到目标系统。在这个最终目的地,我可以看到应该在.zip文件上运行的进程失败(注意:该进程由Rails应用程序运行并提供错误&#34;识别包类型时出错:不能复制NilClass&#34;)。下载文件后,我看到文件大小为3,110,416字节而不是3,110,466字节。我无法再提取存档以查看其中的内容; mac存档实用程序响应&#34;错误2 - 没有这样的文件或目录&#34;。
我缺乏这方面的概念背景,无法了解过程中可能出现的问题。我希望有人能够告诉我,我在实用程序类中犯了一个错误,或者让我知道其他问题。
感谢您提供的任何见解,如果我发布任何有用的信息,请告诉我。
编辑:我收集了一些关于不同大小的文件上传(以字节为单位)的其他信息:
原---------- ----------上传差分
10167389 ______ 10167238 ______ 151
3110466 _______ 3110416 _______ 50
156885 _________ 156885 _________ 0
95639352 ______ 95637925 ______ 1427
对于上传后丢失字节的3个文件,每个数据丢失的百分比大约为(但不完全相同)0.0015%,但不相等。
答案 0 :(得分:0)
经过一些进一步的研究,我们发现该错误与multipart / form-data实用程序没有任何关系,如本问题所示。相反,它与here中我们自己的文件下载客户端有关。我们没有将FileTransfer客户端设置为以二进制形式下载文件,这对于.zip文件是必需的。
您可以随意使用原始问题中包含的代码来实现java中的多部分/表单数据目的 - 假设您的原始文件没有问题,它会很有效。