使用java

时间:2016-01-06 22:02:11

标签: java file-upload amazon-s3 multipartform-data

我在将.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 NotesCodeJava.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%,但不相等。

1 个答案:

答案 0 :(得分:0)

经过一些进一步的研究,我们发现该错误与multipart / form-data实用程序没有任何关系,如本问题所示。相反,它与here中我们自己的文件下载客户端有关。我们没有将FileTransfer客户端设置为以二进制形式下载文件,这对于.zip文件是必需的。

您可以随意使用原始问题中包含的代码来实现java中的多部分/表单数据目的 - 假设您的原始文件没有问题,它会很有效。