在Java中将大文件转换为base64表示形式;内存不足异常

时间:2019-05-20 13:12:36

标签: java base64

我遇到一种情况,我需要以这种格式从后端向前端传输对象:

{
    filename: "filename",
    type: "type",
    src: "src",
    bytes: "base64Representation"
}

对象的bytes属性包含存储在远程服务器的存储库中的文件的base64表示形式。到目前为止,我已经处理了1-2MB的小文件,并且将文件转换为相应的base64表示形式的代码已经正常工作。但是现在我遇到了大于100MB的大文件的一些问题。我已经检查了尝试逐块转换文件块的解决方案,但仍然在过程结束时,我需要将所有块串联在一个字符串中,并且在此步骤中,我遇到 OutOfMemory 异常。我还看到了一些使用 OutputStreams 的建议,但由于我需要上述格式的数据,因此无法应用它们。请问有人对我如何绕过这种情况有任何建议吗?

3 个答案:

答案 0 :(得分:1)

您可以使用OutputStream并通过包装response.getOutputStream()在servlet中进行动态处理。我将用Spring Boot给出一个工作示例。我已经测试过并且可以正常工作。

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Base64;

@RestController
public class Base64Controller {

    @RequestMapping(value = "/base64", method = RequestMethod.GET)
    public void getBase64File(HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
        OutputStream wrap = Base64.getEncoder().wrap(response.getOutputStream());
        FileInputStream fis = new FileInputStream("./temp.txt");
        int bytes;
        byte[] buffer = new byte[2048];
        while ((bytes=fis.read(buffer)) != -1) {
            wrap.write(buffer, 0, bytes);
        }
        fis.close();
        wrap.close();
    }

}

答案 1 :(得分:1)

这里的JSON响应非常麻烦,因为Base64的有效负载为每字节6/8,因此您可以根据需要增加33%的数据传输。确实,JSON DOM对象使服务器和客户端都过度拉伸。

因此将其转换为简单的二进制下载文件,并将其流式传输出去;可能因大数据而受到限制。

这意味着API发生了变化。

答案 2 :(得分:0)

我从来没有使用struts,所以我不确定是否可以使用它,但是应该是这样的

public class DownloadB64Action extends Action{

    private final static BUFFER_SIZE = 1024;

   @Override
   public ActionForward execute(ActionMapping mapping, ActionForm form,
     HttpServletRequest request, HttpServletResponse response)
     throws Exception {

     response.setContentType("text/plain");

     try 
     {

        FileInputStream in = 
            new FileInputStream(new File("myfile.b64"));

        ServletOutputStream out = Base64.getEncoder().wrap(response.getOutputStream());

        byte[] buffer = new byte[BUFFER_SIZE];

        while(in.read(buffer, 0, BUFFER_SIZE) != -1){
            out.write(buffer, 0, BUFFER_SIZE);
        }
        in.close();
        out.flush();
        out.close();

     }catch(Exception e){
        //TODO handle exception
   }

   return null;
  }
}

要使其成为所需的JSON结构,您可以尝试在b64有效负载之前直接写入response.getOutputStream() "{\"filename\":\"filename\",\"type\":\"type\",\"src\":\"src\",\"bytes\": \"".getBytes(),在b64有效负载之后直接写入"\"}".getBytes()

}