目录
问题场景
spring boot 版本:2.2.2
应用网关:shenyu网关(soul网关)
错误描述
在一次项目中,我在上传文件时被网关拦截出现了这个问题:DataBufferLimitException: Exceeded limit on max bytes to buffer :262144,发现只能上传256KB以下的文件,但现在文件随便就是10M或者更大。
具体错误如下:
org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144
at org.springframework.core.io.buffer.LimitedDataBufferList.raiseLimitException(LimitedDataBufferList.java:101)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Stack trace:
at org.springframework.core.io.buffer.LimitedDataBufferList.raiseLimitException(LimitedDataBufferList.java:101)
at org.springframework.core.io.buffer.LimitedDataBufferList.updateCount(LimitedDataBufferList.java:94)
at
解决方案
方案一(对我不生效)
一般来说直接设置 max-in-memory-size 就可以生效
spring:
codec:
max-in-memory-size: 100MB
但是以上代码在spring2.x.x版本中不生效,官方说解决了,估计是在后面版本解决了,但是项目都上生产了肯定不可能现在来换版本,所以只有另想办法,在他启动中debug发现在初始化代码时已经设置为262144了:
方案二(有效)
于是继续往上发现在 org.springframework.core.codec.AbstractDataBufferDecoder中进行初始化的,于是诞生了写一个同名类来给他初始化,利用Spring中同名Bean相互覆盖的特性,在我们注入了同名bean就会优先使用我们的类。
层级目录如下:
我们要保证这个类的包名和spring的名称一模一样,具体代码不变,只需修改maxInMemorySize 大小,如下所示:
package org.springframework.core.codec;
import java.util.Map;
import org.reactivestreams.Publisher;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.MimeType;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @Auther: whhh
* @Date: 2021/4/7 11:08
* @Description: 图片上传重写缓存区大小,解决上传图片缓存不够问题
*/
public abstract class AbstractDataBufferDecoder<T> extends AbstractDecoder<T> {
//图片上传重写缓存区大小,解决上传图片缓存不够问题
private int maxInMemorySize = 1024*1024*100;
protected AbstractDataBufferDecoder(MimeType... supportedMimeTypes) {
super(supportedMimeTypes);
}
public void setMaxInMemorySize(int byteCount) {
this.maxInMemorySize = byteCount;
}
public int getMaxInMemorySize() {
return this.maxInMemorySize;
}
public Flux<T> decode(Publisher<DataBuffer> input, ResolvableType elementType, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
return Flux.from(input).map((buffer) -> {
return this.decodeDataBuffer(buffer, elementType, mimeType, hints);
});
}
public Mono<T> decodeToMono(Publisher<DataBuffer> input, ResolvableType elementType, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
return DataBufferUtils.join(input, this.maxInMemorySize).map((buffer) -> {
return this.decodeDataBuffer(buffer, elementType, mimeType, hints);
});
}
/** @deprecated */
@Deprecated
@Nullable
protected T decodeDataBuffer(DataBuffer buffer, ResolvableType elementType, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
return this.decode(buffer, elementType, mimeType, hints);
}
}
重点就是这里,他会去读取这个配置:
到这里我们的问题就解决了,上传文件就成功了。