程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

Spring boot中分块上传大文件的最佳实践

发布于2021-08-06 00:26     阅读(644)     评论(0)     点赞(25)     收藏(5)


我有一个大文件,我想在服务器端上传它。如果我重试上传、从简历上传文件并且不需要从头发送文件,那么在发生任何问题(例如中断互联网或断电...)时,这一点非常重要

我尝试使用这种方法发送文件块,但这似乎不是一个好方法,因为直接在响应实体中发送块(字节数组),这不是一个好主意。

不管是否有人可以开发这种方法并使此代码成为具有更好性能的更好代码,我对此表示赞赏。有没有人知道这样做的最佳实践方法

如果你喜欢我的代码,请投票给我谢谢:)

休息控制器

@RestController
@RequestMapping("/files")
public class Controller {

@Autowired
private MyService service;

@PutMapping("/upload/resume")
public Mono<ResponseEntity> uploadWithResume(@RequestPart("chunk")byte[] chunk,
                                             @RequestPart("fileName")String fileName,
                                             @RequestParam("length")Long length
) throws ParseException {
    try {
        return service.fileResumeUpload(chunk, fileName, length);
    } catch (IOException e) {
        e.printStackTrace();
        return Mono.just(ResponseEntity.status(HttpStatus.PERMANENT_REDIRECT).build());
    }
}

@RequestMapping(value = "/get/uploaded/size", method = RequestMethod.HEAD)
public Mono<ResponseEntity> getUploadedSize(@RequestParam("fileName") String fileName) throws IOException {
    if (Files.exists(Paths.get("src/main/resources/" + fileName))) {

        String size = String.valueOf(Files.size(Paths.get("src/main/resources/" + fileName)));

        return Mono.just(ResponseEntity.ok()
                .header("upload-offset", size)
                .build());
    } else{
        return Mono.just(ResponseEntity.notFound()
                .header("upload-offset" , "0").build());
    }
}
}

服务

public Mono<ResponseEntity> fileResumeUpload(byte[] chunk , String fileName,long length) throws IOException, ParseException {
    BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("src/main/resources/" + fileName, true));

    boolean uploaded = true;

    try {
        out.write(chunk);
    } catch (IOException e) {
        uploaded = false;
        System.err.println("io exception");
    } finally {
        if (uploaded) {
            out.close();
                return Mono.just(ResponseEntity.ok()
                        .header("expiration-date", getExpirationDate())
                        .build());
        } else {
            out.close();
            return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build());
        }
    }
}

使用 webTestClient 发送块

  @Test
public void test1_upload_Expected_200StatusCode(){
    try {

        String fileName = "film.mkv";

        RandomAccessFile raf = new RandomAccessFile(new File("src/test/resources/" + fileName), "rw");
        long realSize = raf.length();
        List<String> strings = webTestClient.head().uri("/files/get/uploaded/size?fileName=" + fileName)
                .exchange().expectBody().returnResult().getResponseHeaders().get("upload-offset");

        long uploadedSize = Long.valueOf(strings.get(0));

        boolean f = false;

        int sizeBuffer = 256 * 1024;
        byte[] buffer = new byte[sizeBuffer];

        MultiValueMap<String, Object> formData;

        WebTestClient.ResponseSpec exchange = null;

        System.out.println("first uploaded Size ; " + uploadedSize);

        raf.seek(uploadedSize);
        while (raf.read(buffer) != -1) {
            formData = new LinkedMultiValueMap<>();
            formData.add("fileName", fileName);
            formData.add("chunk", buffer);
            formData.add("length", realSize);

            exchange = webTestClient.put().uri("/files/upload/resume")
                    .contentType(MediaType.MULTIPART_FORM_DATA)
                    .body(BodyInserters.fromMultipartData(formData))
                    .exchange();
            exchange.expectStatus().isOk();
            if (exchange.expectBody().returnResult().getStatus().is5xxServerError()) {
                return;
            }


            if (uploadedSize + 256 * 1024 > realSize) {
                sizeBuffer = ((int) (realSize - uploadedSize));
                System.out.println(sizeBuffer);
                uploadedSize = uploadedSize + sizeBuffer;
                System.out.println(uploadedSize);
                buffer = new byte[sizeBuffer];
                f=true;
            } else uploadedSize = uploadedSize + sizeBuffer;

            if (f) System.out.println(uploadedSize);
            //System.out.println(uploadedSize);

            float percent = ((float) uploadedSize / realSize * 100);
            System.out.format("%.2f\n", percent);
        }
        if (exchange!=null)
            exchange.expectStatus().isOk();
    }
    catch (Exception e){
        e.printStackTrace();
        System.err.println("channel closed!!!");
    }
}

解决方案


暂无回答



所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:http://www.javaheidong.com/blog/article/254884/e4d360fe9315f2bad925/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

25 0
收藏该文
已收藏

评论内容:(最多支持255个字符)