美文网首页
Failed to bind properties under

Failed to bind properties under

作者: 爱的旋转体 | 来源:发表于2020-08-12 09:12 被阅读0次

    1 springboot升级版本后,上传文件配置报错:

    Description:
    
    Failed to bind properties under 'spring.servlet.multipart.max-request-size' to org.springframework.util.unit.DataSize:
    
        Property: spring.servlet.multipart.max-request-size
        Value: 100Mb
        Origin: class path resource [config/application.yml]:78:31
        Reason: failed to convert java.lang.String to org.springframework.util.unit.DataSize
    
    Action:
    
    Update your application's configuration
    

    之前的配置是:

        servlet:
            multipart:
                max-file-size: 100Mb
                max-request-size: 100Mb
    

    2 分析原因

    2.1 MultipartProperties

    可以看出,需要DataSize类型

    /*
     * Copyright 2012-2019 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      https://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.boot.autoconfigure.web.servlet;
    
    import javax.servlet.MultipartConfigElement;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.context.properties.PropertyMapper;
    import org.springframework.boot.web.servlet.MultipartConfigFactory;
    import org.springframework.util.unit.DataSize;
    
    /**
     * Properties to be used in configuring a {@link MultipartConfigElement}.
     * <ul>
     * <li>{@link #getLocation() location} specifies the directory where uploaded files will
     * be stored. When not specified, a temporary directory will be used.</li>
     * <li>{@link #getMaxFileSize() max-file-size} specifies the maximum size permitted for
     * uploaded files. The default is 1MB</li>
     * <li>{@link #getMaxRequestSize() max-request-size} specifies the maximum size allowed
     * for {@literal multipart/form-data} requests. The default is 10MB.</li>
     * <li>{@link #getFileSizeThreshold() file-size-threshold} specifies the size threshold
     * after which files will be written to disk. The default is 0.</li>
     * </ul>
     * <p>
     * These properties are ultimately passed to {@link MultipartConfigFactory} which means
     * you may specify numeric values using {@literal long} values or using more readable
     * {@link DataSize} variants.
     *
     * @author Josh Long
     * @author Toshiaki Maki
     * @author Stephane Nicoll
     * @since 2.0.0
     */
    @ConfigurationProperties(prefix = "spring.servlet.multipart", ignoreUnknownFields = false)
    public class MultipartProperties {
    
        /**
         * Whether to enable support of multipart uploads.
         */
        private boolean enabled = true;
    
        /**
         * Intermediate location of uploaded files.
         */
        private String location;
    
        /**
         * Max file size.
         */
        private DataSize maxFileSize = DataSize.ofMegabytes(1);
    
        /**
         * Max request size.
         */
        private DataSize maxRequestSize = DataSize.ofMegabytes(10);
    
        /**
         * Threshold after which files are written to disk.
         */
        private DataSize fileSizeThreshold = DataSize.ofBytes(0);
    
        /**
         * Whether to resolve the multipart request lazily at the time of file or parameter
         * access.
         */
        private boolean resolveLazily = false;
    
        public boolean getEnabled() {
            return this.enabled;
        }
    
        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    
        public String getLocation() {
            return this.location;
        }
    
        public void setLocation(String location) {
            this.location = location;
        }
    
        public DataSize getMaxFileSize() {
            return this.maxFileSize;
        }
    
        public void setMaxFileSize(DataSize maxFileSize) {
            this.maxFileSize = maxFileSize;
        }
    
        public DataSize getMaxRequestSize() {
            return this.maxRequestSize;
        }
    
        public void setMaxRequestSize(DataSize maxRequestSize) {
            this.maxRequestSize = maxRequestSize;
        }
    
        public DataSize getFileSizeThreshold() {
            return this.fileSizeThreshold;
        }
    
        public void setFileSizeThreshold(DataSize fileSizeThreshold) {
            this.fileSizeThreshold = fileSizeThreshold;
        }
    
        public boolean isResolveLazily() {
            return this.resolveLazily;
        }
    
        public void setResolveLazily(boolean resolveLazily) {
            this.resolveLazily = resolveLazily;
        }
    
        /**
         * Create a new {@link MultipartConfigElement} using the properties.
         * @return a new {@link MultipartConfigElement} configured using there properties
         */
        public MultipartConfigElement createMultipartConfig() {
            MultipartConfigFactory factory = new MultipartConfigFactory();
            PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
            map.from(this.fileSizeThreshold).to(factory::setFileSizeThreshold);
            map.from(this.location).whenHasText().to(factory::setLocation);
            map.from(this.maxRequestSize).to(factory::setMaxRequestSize);
            map.from(this.maxFileSize).to(factory::setMaxFileSize);
            return factory.createMultipartConfig();
        }
    
    }
    

    2.2 DataSize

    根据注释可以看出,需要大写的MB

    /*
     * Copyright 2002-2019 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      https://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.util.unit;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import org.springframework.lang.Nullable;
    import org.springframework.util.Assert;
    import org.springframework.util.StringUtils;
    
    /**
     * A data size, such as '12MB'.
     *
     * <p>This class models data size in terms of bytes and is immutable and thread-safe.
     *
     * <p>The terms and units used in this class are based on
     * <a href="https://en.wikipedia.org/wiki/Binary_prefix">binary prefixes</a>
     * indicating multiplication by powers of 2. Consult the following table and
     * the Javadoc for {@link DataUnit} for details.
     *
     * <p>
     * <table border="1">
     * <tr><th>Term</th><th>Data Size</th><th>Size in Bytes</th></tr>
     * <tr><td>byte</td><td>1B</td><td>1</td></tr>
     * <tr><td>kilobyte</td><td>1KB</td><td>1,024</td></tr>
     * <tr><td>megabyte</td><td>1MB</td><td>1,048,576</td></tr>
     * <tr><td>gigabyte</td><td>1GB</td><td>1,073,741,824</td></tr>
     * <tr><td>terabyte</td><td>1TB</td><td>1,099,511,627,776</td></tr>
     * </table>
     *
     * @author Stephane Nicoll
     * @author Sam Brannen
     * @since 5.1
     * @see DataUnit
     */
    public final class DataSize implements Comparable<DataSize> {
    
        /**
         * The pattern for parsing.
         */
        private static final Pattern PATTERN = Pattern.compile("^([+\\-]?\\d+)([a-zA-Z]{0,2})$");
    
        /**
         * Bytes per Kilobyte.
         */
        private static final long BYTES_PER_KB = 1024;
    
        /**
         * Bytes per Megabyte.
         */
        private static final long BYTES_PER_MB = BYTES_PER_KB * 1024;
    
        /**
         * Bytes per Gigabyte.
         */
        private static final long BYTES_PER_GB = BYTES_PER_MB * 1024;
    
        /**
         * Bytes per Terabyte.
         */
        private static final long BYTES_PER_TB = BYTES_PER_GB * 1024;
    
    
        private final long bytes;
    
    
        private DataSize(long bytes) {
            this.bytes = bytes;
        }
    
    
        /**
         * Obtain a {@link DataSize} representing the specified number of bytes.
         * @param bytes the number of bytes, positive or negative
         * @return a {@link DataSize}
         */
        public static DataSize ofBytes(long bytes) {
            return new DataSize(bytes);
        }
    
        /**
         * Obtain a {@link DataSize} representing the specified number of kilobytes.
         * @param kilobytes the number of kilobytes, positive or negative
         * @return a {@link DataSize}
         */
        public static DataSize ofKilobytes(long kilobytes) {
            return new DataSize(Math.multiplyExact(kilobytes, BYTES_PER_KB));
        }
    
        /**
         * Obtain a {@link DataSize} representing the specified number of megabytes.
         * @param megabytes the number of megabytes, positive or negative
         * @return a {@link DataSize}
         */
        public static DataSize ofMegabytes(long megabytes) {
            return new DataSize(Math.multiplyExact(megabytes, BYTES_PER_MB));
        }
    
        /**
         * Obtain a {@link DataSize} representing the specified number of gigabytes.
         * @param gigabytes the number of gigabytes, positive or negative
         * @return a {@link DataSize}
         */
        public static DataSize ofGigabytes(long gigabytes) {
            return new DataSize(Math.multiplyExact(gigabytes, BYTES_PER_GB));
        }
    
        /**
         * Obtain a {@link DataSize} representing the specified number of terabytes.
         * @param terabytes the number of terabytes, positive or negative
         * @return a {@link DataSize}
         */
        public static DataSize ofTerabytes(long terabytes) {
            return new DataSize(Math.multiplyExact(terabytes, BYTES_PER_TB));
        }
    
        /**
         * Obtain a {@link DataSize} representing an amount in the specified {@link DataUnit}.
         * @param amount the amount of the size, measured in terms of the unit,
         * positive or negative
         * @return a corresponding {@link DataSize}
         */
        public static DataSize of(long amount, DataUnit unit) {
            Assert.notNull(unit, "Unit must not be null");
            return new DataSize(Math.multiplyExact(amount, unit.size().toBytes()));
        }
    
        /**
         * Obtain a {@link DataSize} from a text string such as {@code 12MB} using
         * {@link DataUnit#BYTES} if no unit is specified.
         * <p>
         * Examples:
         * <pre>
         * "12KB" -- parses as "12 kilobytes"
         * "5MB"  -- parses as "5 megabytes"
         * "20"   -- parses as "20 bytes"
         * </pre>
         * @param text the text to parse
         * @return the parsed {@link DataSize}
         * @see #parse(CharSequence, DataUnit)
         */
        public static DataSize parse(CharSequence text) {
            return parse(text, null);
        }
    
        /**
         * Obtain a {@link DataSize} from a text string such as {@code 12MB} using
         * the specified default {@link DataUnit} if no unit is specified.
         * <p>
         * The string starts with a number followed optionally by a unit matching one of the
         * supported {@linkplain DataUnit suffixes}.
         * <p>
         * Examples:
         * <pre>
         * "12KB" -- parses as "12 kilobytes"
         * "5MB"  -- parses as "5 megabytes"
         * "20"   -- parses as "20 kilobytes" (where the {@code defaultUnit} is {@link DataUnit#KILOBYTES})
         * </pre>
         * @param text the text to parse
         * @return the parsed {@link DataSize}
         */
        public static DataSize parse(CharSequence text, @Nullable DataUnit defaultUnit) {
            Assert.notNull(text, "Text must not be null");
            try {
                Matcher matcher = PATTERN.matcher(text);
                Assert.state(matcher.matches(), "Does not match data size pattern");
                DataUnit unit = determineDataUnit(matcher.group(2), defaultUnit);
                long amount = Long.parseLong(matcher.group(1));
                return DataSize.of(amount, unit);
            }
            catch (Exception ex) {
                throw new IllegalArgumentException("'" + text + "' is not a valid data size", ex);
            }
        }
    
        private static DataUnit determineDataUnit(String suffix, @Nullable DataUnit defaultUnit) {
            DataUnit defaultUnitToUse = (defaultUnit != null ? defaultUnit : DataUnit.BYTES);
            return (StringUtils.hasLength(suffix) ? DataUnit.fromSuffix(suffix) : defaultUnitToUse);
        }
    
        /**
         * Checks if this size is negative, excluding zero.
         * @return true if this size has a size less than zero bytes
         */
        public boolean isNegative() {
            return this.bytes < 0;
        }
    
        /**
         * Return the number of bytes in this instance.
         * @return the number of bytes
         */
        public long toBytes() {
            return this.bytes;
        }
    
        /**
         * Return the number of kilobytes in this instance.
         * @return the number of kilobytes
         */
        public long toKilobytes() {
            return this.bytes / BYTES_PER_KB;
        }
    
        /**
         * Return the number of megabytes in this instance.
         * @return the number of megabytes
         */
        public long toMegabytes() {
            return this.bytes / BYTES_PER_MB;
        }
    
        /**
         * Return the number of gigabytes in this instance.
         * @return the number of gigabytes
         */
        public long toGigabytes() {
            return this.bytes / BYTES_PER_GB;
        }
    
        /**
         * Return the number of terabytes in this instance.
         * @return the number of terabytes
         */
        public long toTerabytes() {
            return this.bytes / BYTES_PER_TB;
        }
    
        @Override
        public int compareTo(DataSize other) {
            return Long.compare(this.bytes, other.bytes);
        }
    
        @Override
        public String toString() {
            return String.format("%dB", this.bytes);
        }
    
    
        @Override
        public boolean equals(@Nullable Object other) {
            if (this == other) {
                return true;
            }
            if (other == null || getClass() != other.getClass()) {
                return false;
            }
            DataSize otherSize = (DataSize) other;
            return (this.bytes == otherSize.bytes);
        }
    
        @Override
        public int hashCode() {
            return Long.hashCode(this.bytes);
        }
    
    }
    

    3 最后的修改结果

      servlet:
            multipart:
                max-file-size: 100MB
                max-request-size: 100MB
    

    相关文章

      网友评论

          本文标题:Failed to bind properties under

          本文链接:https://www.haomeiwen.com/subject/xqcpdktx.html