Azure Blob 存储连接

Azure Blob Storage Connection

我在使用 Azure Blob 存储时遇到问题,当我想上传图像时出现错误

Caused by: java.lang.IllegalArgumentException: prefetch > 0 required but it was 0
    at reactor.core.publisher.FluxConcatMap.<init>(FluxConcatMap.java:101) ~[reactor-core-3.3.12.RELEASE.jar:3.3.12.RELEASE]
    at reactor.core.publisher.Flux.concatMap(Flux.java:3673) ~[reactor-core-3.3.12.RELEASE.jar:3.3.12.RELEASE]
    at com.azure.storage.common.implementation.UploadUtils.uploadFullOrChunked(UploadUtils.java:52) ~[azure-storage-common-12.14.0.jar:12.14.0]
    at com.azure.storage.blob.BlobAsyncClient.uploadWithResponse(BlobAsyncClient.java:600) ~[azure-storage-blob-12.14.1.jar:12.14.1]
    at com.azure.storage.blob.BlobAsyncClient.uploadWithResponse(BlobAsyncClient.java:491) ~[azure-storage-blob-12.14.1.jar:12.14.1]
    at com.azure.storage.blob.BlobAsyncClient.upload(BlobAsyncClient.java:381) ~[azure-storage-blob-12.14.1.jar:12.14.1]
    at com.kypnt.edutest.testcentreservice.service.ImageService.upload(ImageService.java:48) ~[main/:na]
    at com.kypnt.edutest.testcentreservice.controller.image.ImageController.uploadImage(ImageController.java:19) ~[main/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
    ... 80 common frames omitted
    Suppressed: java.lang.Exception: #block terminated with an error
        at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99) ~[reactor-core-3.3.12.RELEASE.jar:3.3.12.RELEASE]
        at reactor.core.publisher.Mono.block(Mono.java:1685) ~[reactor-core-3.3.12.RELEASE.jar:3.3.12.RELEASE]
        ... 93 common frames omitted

我用谷歌搜索了这个,但找不到原因。

我的配置:

@Configuration
public class AzureStorageBlobClientConfig {

    @Value("${azure.storage.connection-string}")
    private String connectionString;

    @Value("${azure.storage.container-name}")
    private String containerName;

    @Bean
    public BlobServiceAsyncClient blobServiceClient() {
        return new BlobServiceClientBuilder().connectionString(connectionString).buildAsyncClient();
    }

    @Bean
    public BlobContainerAsyncClient blobAsyncClient() {
        return blobServiceClient().getBlobContainerAsyncClient(containerName);
    }
}

我的服务:

@Slf4j
@Service
public class ImageService {

    @Autowired
    private BlobContainerAsyncClient blobContainerAsyncClient;

    private int blockSize = 10 * 1024;
    private int numBuffers = 5;

    public MyResponse<?> upload(MultipartFile file) {

        if (file.isEmpty())
            throw new BadRequestException("No File");

        String fileName = UUID.randomUUID() + file.getOriginalFilename();

        try {
            BlobAsyncClient blobAsyncClient = blobContainerAsyncClient.getBlobAsyncClient(fileName);

            Flux<ByteBuffer> data = Flux.just(ByteBuffer.wrap(file.getInputStream().readAllBytes()));

            ParallelTransferOptions parallelTransferOptions = new ParallelTransferOptions(numBuffers, blockSize, null);

            blobAsyncClient.upload(data, parallelTransferOptions, true).block();

//            BlobContainerClient container = new BlobContainerClientBuilder()
//                    .connectionString(connectionString)
//                    .containerName(containerName)
//                    .buildClient();
//
//            BlobClient blobClient = container.getBlobClient(fileName);
//
//            blobClient.upload(file.getInputStream(), file.getSize(), true);

//            blobClient
//                    .blobName(fileName)
//                    .buildClient()
//                    .upload(file.getInputStream(), file.getSize());
        } catch (IOException e) {
            log.warn(e.getMessage());
//                throw new EdutestException(ErrorType.INTERNAL_ERROR);
        }

        return new OKResponse<>("Good");
    }

}

那些注释代码,我试过的教程,但都返回这个异常。

在那里我得到了我的连接字符串和创建的容器并得到了它的名字:

我的gradle:

plugins {
    id 'org.springframework.boot' version '2.3.7.RELEASE'
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}

// some code

dependencies {
    implementation 'com.azure:azure-storage-blob:12.14.1'
    implementation group: 'com.azure', name: 'azure-identity', version: '1.4.1'
}

// some code

最后我发现问题出在新版本的“azure storage blob” 它使用新的 'reactor-netty-core' 和 'reactor-netty-http' 但使用旧代码或类似的东西,请阅读 here

要修复它,请使用旧版本:

implementation group: 'com.azure.spring', name: 'azure-spring-boot-starter-storage', version: '3.1.0'

您可以使用这个版本。当存在问题时,我使用版本“3.10.0”。没有测试其他版本。