动态

详情 返回 返回

Java-實現axios上傳文件接口攜帶多參數 - 动态 详情

前言

最近在實現小圖片上傳的過程中剛開始我使用base64字符串做為後台接口參數傳遞給後台並解析保存也沒問題,但是發現第2次及之後就報下面的錯:

org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144

然後問了AI給的回覆如下:

這個問題通常是由於 Spring Boot 默認的 DataBuffer 限制導致的,默認限制為 256 KB。當你傳遞大於這個大小的 Base64 字符串時,就會出現 DataBufferLimitException。

那沒辦法,所以我只能退一步使用上傳File來實現了,以為自己可以減少工作量,唉,乖乖實現吧!

但是有個問題就是我不僅要上傳文件,還要攜帶參數,之前沒有這樣的需求,如何做呢?

操作

問了AI,下面是實現前端代碼,如下所示:

antd代碼:

const props2 = {
        // 不顯示上傳文件列表
        showUploadList: false,
        // name: 'file',
        accept: "image/png, image/jpeg",
        multiple: false,
        maxCount: 1,
        beforeUpload: async (file) => {
            console.log('file=>', file)
            const isLt2M = file.size / 1024 / 1024 < 2;
            if (!isLt2M) {
                message.error('二維碼上傳文件不能大於2MB!');
            }

            setDlg({
                type: 'saveAndRead',
                title: '保存到我的文件',
                show: true,
                // 使用marked把markdown格式轉換成html格式供ckeditor富文本編輯器使用
                data: {
                    name: '',
                    file: file
                },
                onSuccess: async (d) => {
                    console.log('success d=', d)
                    if (d?.text){
                        message.success("解析成功")
                        setParsingQrcode2(d.text)
                    }else{
                        message.error("解析失敗")
                    }
                }
            })
            return false;
        },
        onDrop(e) {
            console.log('Dropped files', e.dataTransfer.files);
        },
    };


 <Dragger {...props2}>
    <div className={'flex w-full flex-col'}>
        <p className="ant-upload-drag-icon">
            <UploadOutlined/>
        </p>
        <p className="ant-upload-text">單擊或將文件拖動到此區域以上傳</p>
        <p className="ant-upload-text">(提示:先上傳到我的文件再解析)</p>
    </div>
</Dragger>

請求接口代碼:

 try {
        const formData = new FormData();
        formData.append('file', params.file);
        formData.append('categoryId', params.categoryId);
        formData.append('fileName', params.fileName);

        const res = await axios.post(`/space/crud/file/addFileForQrcodeAndRead`, formData);
        return res.data
    } catch (error) {
        return thunkAPI.rejectWithValue({errorMsg: error.message});
    }

後台實現:

@PostMapping("/crud/file/addFileForQrcodeAndRead")
public Mono<ResponseEntity<?>> addFileForQrcodeAndRead(@RequestPart("file") Mono<FilePart> file,
                                                           @RequestPart("categoryId") String cid,
                                                           @RequestPart("fileName") String filename) throws IOException {
        LoginUser loginUser = UserContext.getUser();
        if (loginUser == null) {
            return Mono.just(ResponseEntity.ok(HttpStatus.UNAUTHORIZED));
        }

        if (!StringUtils.hasLength(cid) || !StringUtils.hasLength(filename)) {
            return Mono.just(ResponseEntity.ok(new ResultInfo<>(ResultStatus.DATA_EMPTY)));
        }


        return file.flatMap(fp -> {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            return fp.content().collectList().flatMap(dataBuffers -> {

                try {
                    dataBuffers.forEach(buffer -> {
                        byte[] bytes = new byte[buffer.readableByteCount()];
                        buffer.read(bytes);
                        baos.write(bytes, 0, bytes.length);
                    });
                    byte[] bytes = baos.toByteArray();
                    Long size = (long) bytes.length;
                    ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
                    BufferedImage bufferedImage = ImageIO.read(inputStream);

                    BufferedImage bufferedImage2 = addBorder(bufferedImage, 20);

                    LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage2);
                    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

                    Result result = new MultiFormatReader().decode(bitmap);

                    // 注意:重置指針,方便第2次讀取,否則下面獲取不到inputStream
                    inputStream.reset();
                    // 是否能檢測到數據,不能檢測數據就添加不成功
                    if (StringUtils.hasLength(result.getText())) {

                    }
                    // 如何二維碼解析出來了,但是添加和上傳圖片失敗,那也返回解析結果
                    return Mono.just(ResponseEntity.ok(new ResultSuccess<>(result)));
                } catch (Exception ex) {
                    log.info("uploadFileAndRead ex={}", ex.getMessage());
                    return Mono.just(ResponseEntity.ok(new ResultInfo<>(ResultStatus.Exception)));
                }
            });
        });

這樣就完成了上傳文件並且攜帶參數了。

總結

1、Base64做為參數傳遞到後台會導致參數大小超過限制,因此使用File上傳。
2、後台接收的時候要統一使用RequestPart,剛開始我使用了下面的代碼就出問題了(AI給的代碼):

public ResponseEntity<?> uploadFileAndRead(
@RequestPart("upload") MultipartFile file,
@RequestParam("additionalParam1") String param1,
@RequestParam("additionalParam2") String param2)

3、文件流inputStream讀取之後再次使用就會拿不到,解決辦法:

inputStream.reset();

AI的回答是這樣的:

ByteArrayInputStream 的數據流被讀取一次後,無法再次讀取,因為 ByteArrayInputStream 的內部指針已經到達了流的末尾。

要解決這個問題,可以在讀取流數據後重置 ByteArrayInputStream,或者在需要重新使用時重新創建 ByteArrayInputStream。

引用

user avatar debuginn 头像 xuxueli 头像 jiangyi 头像 huangxunhui 头像 nianqingyouweidenangua 头像 wuliaodechaye 头像 chenjiabing666 头像 xiaoxiansheng_5e75673e1ae30 头像 ruozxby 头像 beishangdeyadan 头像 enaium 头像 qqxx6661 头像
点赞 28 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.