当前位置: 首页 > 知识库问答 >
问题:

使用Java上载包含多部分/表单数据的zip文件时缺少字节

归翔
2023-03-14

我在将.zip文件上载到远程服务器时遇到了一个问题,因为上载后文件中丢失了一些字节。在重新下载文件时,.zip存档是不可打开的,这使我相信我需要这些字节来成功地执行上传。

我正在使用多部分/表单数据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);
    }
}

在本例中,上传url是给AmazonS3桶的,该桶将其传递给目标系统。正是在这个最终目的地,我可以看到应该在.zip文件上运行的进程失败了(注意:该进程由一个Rails应用程序运行,并给出错误“error Identification package Type:can't dup NilClass”)。下载文件时,我看到文件大小是3,110,416字节,而不是3,110,466字节。我再也无法提取存档来查看其中的内容;mac存档实用程序响应“错误2-没有这样的文件或目录”。

我缺乏这方面的概念性背景,无法对过程中可能出问题的地方有所感觉。我希望有人能告诉我,我在实用程序类中犯了一个错误,或者让我知道是别的问题。

谢谢你的任何见解,你可以提供,并让我知道,如果我可以张贴任何其他将会有帮助。

编辑:我收集到的关于不同大小文件上载的一些附加信息(以字节为单位):

原始----------上载---------差异

10,167,389______10,167,238______151

3,110,466_____3,110,416_______50

156,885_________156,885__________0

95,639,352_____95,637,925_____1,427

对于上传后丢失字节的3个文件,每个文件丢失的总数据的百分比大约(但不完全)0.0015%,但彼此不相等。

共有1个答案

方河
2023-03-14

经过进一步的研究,我们发现该错误与本问题中所示的multipart/form-data实用程序无关。取而代之的是,这与我们自己的文件下载客户端有关。我们没有将FileTransfer客户端设置为将文件下载为二进制文件,而二进制文件是.zip文件所必需的。

在Java,您可以随意使用问题中包含的代码来实现多部分/表单数据的目的--如果您的原始文件没有问题,它就会很好地工作。

 类似资料:
  • 我正在尝试使用Support Bee API创建附件,如下所述:https://supportbee.com/api#create_attachment 我编写了一个服务,它使用创建并发送使用文件名的请求。 如果我在《邮递员》中测试,它会成功。我正在为正文使用,只是从UI中选择要上载的文件: 当我试图通过我的服务上传它时,它不起作用: 这将导致500内部服务器错误。检查对象时,我可以看到它的标题值

  • 我正在尝试在 Java 应用程序中设置一个 Apache Camel 路由,其中使用者终结点是一个 restlet 组件,它将 HTTP 文件上传作为多部分表单数据的 POST 进行处理,然后创建者终结点将请求转发到也接受多部分表单数据的 rest 服务。我是骆驼的新手,不知道如何正确地连接它。以下是到目前为止我的路线。我是否需要对正文进行任何转换,还是会按原样转发多部分表单数据?有人可以为我提供

  • 我试图发送一个帖子请求到一个php文件,该文件有帖子数据和文件上传,这里是我发送的内容,设置标题的代码,我有的php文件,以及我从php中得到的东西file:([图像文件内容]是我正在发送的图像文件二进制数据的占位符) 我的问题是_POST //我正在向服务器发送的数据: 对于我的标题,我有: php文件: php文件的结果:

  • 谢谢你过来。 我想使用fetch api发送一个作为请求的 手术看起来像这样 这里的问题是边界,比如 永远不要将其放入标题中 应该是这样的 当您使用尝试“相同”操作时,如下所示 标题设置正确 所以我的问题是, > 在这种情况下,我如何使的行为完全像? 如果这不可能,为什么? 谢谢大家!这个社区或多或少是我职业成功的原因。

  • 问题内容: 我正在尝试通过jQuery.Form插件提交带有字段的表单,下面是代码: 然后,服务器返回json作为响应。在IE(试图将响应下载为文件)中的所有浏览器中都可以正常工作。如果我从表单中删除文件字段,它也可以正常工作。 我在这里和Google中已经看到了各种解决方案,并且基本上尝试了几乎所有描述的方法,包括通过jQuery 设置表单,但是没有用。 任何建议都将受到欢迎。 问题答案: 我没

  • 问题内容: 我有一个代码库,当前使用Post上传文件,并具有enctype作为multipart / form- data。现在,我需要包括一些表单项,即一些参数也将随文件上传一起传递。我已经创建了html表单,但是我不能使用request.getParameter,因为它是一个多部分表单。谁能建议我如何将参数与上传文件一起传递。我提供以下代码。请根据我的代码的兼容性建议我如何解决 问题答案: 如