以块的形式发送上传以避免使用httpclient 3.1和URLConnection的OutOfMemoryError

时间:2014-08-01 03:28:57

标签: java apache urlconnection apache-commons-httpclient jdk1.4

我正在尝试使用apache commons httpclient 3.1将文件发送到IIS服务器,但是我的内存出错了。

    InputStream is = FileService.getInputStream(fileName, FileService.HDD);
    ByteArrayOutputStream fileToUpload = new ByteArrayOutputStream();
    ByteArrayPartSource file = null;

    try {
        byte[] buffer = new byte[1024];
        for (int len; (len = is.read(buffer)) != -1;)
            fileToUpload.write(buffer, 0, len);

        file = new ByteArrayPartSource(fileName, fileToUpload.toByteArray());

        post.setContentChunked(false); 
        Part[] part = new Part[] { new FilePart(fileName, file)}; 
        post.setRequestEntity(new MultipartRequestEntity(part, post.getParams())); 
    }
    catch (OutOfMemoryError e) {
    }
    finally {
        try {
            if (is != null) is.close();
            if (fileToUpload != null) fileToUpload.close();
        } catch (IOException e) {
        }
    }

OutOfMemoryError发生在fileToUpload.toByteArray()。有没有办法以块的形式发送文件?我无法使用文件对象,因为我收到了权限错误。

我也尝试过不使用httpClient,但我仍然出现内存错误

    InputStream fileToUpload = FileService.getInputStream(fileName, FileService.HDD);
    OutputStream output = connection.getOutputStream();
    PrintWriter writer = null;

    try {
        writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));

        writer.println("--" + boundary);
        writer.println("Content-Disposition: form-data; name=\"binaryFile\"; filename=\""+ fileName + "\"");
        writer.println("Content-Type: application/octet-stream");
        writer.println("Content-Transfer-Encoding: binary");
        writer.println();
        writer.flush();

        LogService.info("FileSender#setFileToUpload() Before");
        byte[] buffer = new byte[2048];
        int bytesRead;
        while ((bytesRead = fileToUpload.read(buffer)) != -1){
            output.write(buffer, 0, bytesRead);
        }

        LogService.info("FileSender#setFileToUpload() After");

        output.flush();
        writer.println();
        writer.flush();
        writer.println("--" + boundary + "--");

    } finally {
         if (writer != null) writer.close();
         if (output != null)  output.close();
         if (fileToUpload != null) fileToUpload.close();
    }

2 个答案:

答案 0 :(得分:0)

您需要对数据进行流式传输,因此它不会像以下内容一样存储在内存中:

    InputStream is = FileService.getInputStream(fileName, FileService.HDD);
    try {
        InputStreamBody inputStreamBody = new InputStreamBody(is, fileName);
        MultipartEntity entity = new MultipartEntity();
        entity.addPart(fileName, inputStreamBody);
        post.setEntity(entity);

        httpClient.execute(post);
        ...
    } finally {
        is.close();
    }

答案 1 :(得分:0)

在非httpclient版本中,尝试移动output.flush(),以便在读取时通过网络发送您读取的块,而不是在刷新之前缓冲整个文件在内存中(您可能想要尝试其他块大小):

    InputStream fileToUpload = FileService.getInputStream(fileName, FileService.HDD);
    OutputStream output = connection.getOutputStream();
    PrintWriter writer = null;

    try {
        writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));

        writer.println("--" + boundary);
        writer.println("Content-Disposition: form-data; name=\"binaryFile\"; filename=\""+ fileName + "\"");
        writer.println("Content-Type: application/octet-stream");
        writer.println("Content-Transfer-Encoding: binary");
        writer.println();
        writer.flush();

        LogService.info("FileSender#setFileToUpload() Before");
        byte[] buffer = new byte[2048];
        int bytesRead;
        while ((bytesRead = fileToUpload.read(buffer)) != -1){
            output.write(buffer, 0, bytesRead);
            output.flush();// <-----------------------------------
        }//                                                      |
        //                                                       |
        LogService.info("FileSender#setFileToUpload() After");// |
        //                                                       |
        // -------------------------------------------------------
        writer.println();
        writer.flush();
        writer.println("--" + boundary + "--");

    } finally {
         if (writer != null) writer.close();
         if (output != null)  output.close();
         if (fileToUpload != null) fileToUpload.close();
    }