【问题标题】:Angular 4 and spring boot large files management:Angular 4 和 spring boot 大文件管理:
【发布时间】:2020-05-18 17:21:11
【问题描述】:

我有一个应用程序需要将大文件(最多几 GB)从客户端保存到服务器。 我遇到的问题是服务器的最大堆大小为 2 GB,而且我经常收到“OutOfMemoryError”。

目前我有这段代码(我知道这不是一个好方法,并且文件完全加载到服务器堆):

Angular 组件 ts:

public void uploadFile() {
    let body = new FormData();
    body.append("file", this.file, this.fileName);
    this.http.post("/uploadFile", body).subscribe(res => {
    alert("success");
    });
}

弹簧控制器:

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
@ResponseBody
public void uploadFile(@RequestParam("file") MultipartFile file) {
    SimpleDDateFormat formatter = new SimpleDDateFormat("dd-mm-yyyy-hh-mm-ss");
    String filename = FILE_DIR_LOCATION + file.getOriginalFileName() + formater.format(new Date());
    InputStream in = new BufferedInputStream(file.getInputStream());

    FileOutputStream fos = new FileOutputStream(filename);
    byte[] buffer = new byte[4096];
    int readedBytes = 0;
    while ((readedBytes = in.read(buffer)) != -1) {
        fos.write(buffer, 0, readedBytes);
        fos.flush;
    }

    fos.close();

}

我想在客户端将文件分成更小的部分,然后像这样将它们发送到服务器,这样可以再次将它们保存为一个文件,而不会占用太多堆。 因为可能同时有多个客户端,并且一个文件可能比堆大。 我找不到这样做的最佳做法,我想到了这样的事情:

Angular 组件 ts:

    static MAX_PART_SIZE = 4096;
    public void uploadFile() {
        this.fileReader = new FileReader();
        this.fileReader.readAsArrayBuffer(this.file);
    }

    public void startSendingFile() {
        this.bytesArray = this.fileReader.result;
        this.http("uploadFirstPart", //send only the MAX_PART_SIZE to the server, size and name).subscribe(res => {
            if (this.bytesArray.length > MAX_PART_SIZE) {
                this.keepSendingToServer(res, this.bytesArray.length - MAX_PART_SIZE);
            }
        });
    }

public void keepSendingToServer(fileName, remainBytes) {
    this.http("uploadPart", //send the next part of the file and if this is the end of the file).subscribe(res => {
        if (remainBytes - MAX_PART_SIZE > 0) {
            this.keepSendingToServer(fileName, remainBytes - MAX_PART_SIZE);
        }
    });
}

弹簧控制器:

Static HashMap<String, FileOutputStream> files = new HashMap<String, FileOutputStream>();

@RequestMapping(value = "/uploadFirstPart", method = RequestMethod.POST)
@ResponseBody
public String uploadFile(@RequestParam("file") byte[] file, @RequestParam("filename") String name, @RequestParam("size") int size) {
    SimpleDDateFormat formatter = new SimpleDDateFormat("dd-mm-yyyy-hh-mm-ss");
    String filename = FILE_DIR_LOCATION + name + formater.format(new Date());

    FileOutputStream fos = new FileOutputStream(filename);
    files.put(filename, fos);

    fos.write(file, 0, size);
    fos.flush;

    return filename;
}

@RequestMapping(value = "/uploadPart", method = RequestMethod.POST)
@ResponseBody
public void uploadPart(@RequestParam("file") byte[] file, @RequestParam("filename") String name, @RequestParam("size") int size, @RequestParam("isEnd") boolean isEnd) {
    FileOutputStream fos = files.get(name);

    fos.write(file, 0, size);
    fos.flush;

    if (isEnd) {
        fos.close();
        files.remove(name);
    }
}

一些问题: 1. 这是最佳实践吗?还有其他方法吗? 2.你能帮我修复代码中的cmets,因为我找不到如何做的事情。 3. 有没有办法只获取想要的字节而不在客户端加载整个大文件(如java中的输入流)? 4. 在我的服务器中,有一个文件以base64字符串发送,另一个以byte[]发送,有没有更好的发送文件方式(文件可以是图像、音频、视频、二进制等)?

【问题讨论】:

    标签: angular spring spring-boot file


    【解决方案1】:

    您可以本地处理请求输入流,以便在上传期间将其写入磁盘。

    请看这里:https://stackoverflow.com/a/38200145/2414811

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-17
      • 2018-10-30
      • 2019-04-15
      • 2021-05-09
      • 2020-11-28
      • 2018-09-04
      • 1970-01-01
      • 2017-12-30
      相关资源
      最近更新 更多