chore: 调整文件上传文件体积展示,转成 KB, MB 等展示,而不是字节 (#5328)

* chore: 调整文件上传文件体积展示,转成 KB, MB 等展示,而不是字节

* 落改了一个

* 修复正则错误

* 修复正则错误
This commit is contained in:
liaoxuezhi 2022-09-09 15:04:20 +08:00 committed by RUNZE LU
parent 157949f27c
commit be0ff2991e
8 changed files with 50 additions and 40 deletions

View File

@ -72,6 +72,26 @@ order: 21
想要限制多个类型,则用逗号分隔,例如:`.csv,.md` 想要限制多个类型,则用逗号分隔,例如:`.csv,.md`
## 限制文件大小
可以配置`maxSize`来限制文件大小
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"type": "input-file",
"name": "file",
"label": "不能上传超过 1M 的文件",
"maxSize": 1048576,
"receiver": "/api/upload/file"
}
]
}
```
## 手动上传 ## 手动上传
如果不希望 File 组件上传,可以配置 `asBlob` 或者 `asBase64`,采用这种方式后,组件不再自己上传了,而是直接把文件数据作为表单项的值,文件内容会在 Form 表单提交的接口里面一起带上。 如果不希望 File 组件上传,可以配置 `asBlob` 或者 `asBase64`,采用这种方式后,组件不再自己上传了,而是直接把文件数据作为表单项的值,文件内容会在 Form 表单提交的接口里面一起带上。

View File

@ -170,7 +170,7 @@ export function formulaExec(
const curValue = value.trim(); // 剔除前后空格 const curValue = value.trim(); // 剔除前后空格
// OpenFormulaExecEvalMode 为 true 时,非 ${ xxx } 格式也会尝试使用表达式运算器 // OpenFormulaExecEvalMode 为 true 时,非 ${ xxx } 格式也会尝试使用表达式运算器
if (OpenFormulaExecEvalMode && /^[0-9a-zA-z_]+$/.test(curValue)) { if (OpenFormulaExecEvalMode && /^[0-9a-zA-Z_]+$/.test(curValue)) {
// 普通字符串类型(非表达式),先试一下从上下文中获取数据 // 普通字符串类型(非表达式),先试一下从上下文中获取数据
const curValueTemp = FormulaExec['var'](curValue, data); const curValueTemp = FormulaExec['var'](curValue, data);
// 备注: 其他特殊格式,比如邮箱、日期 // 备注: 其他特殊格式,比如邮箱、日期

View File

@ -1,6 +1,6 @@
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
export const prettyBytes = (num: number) => { export const prettyBytes = (num: number, step = 1000) => {
if (!Number.isFinite(num)) { if (!Number.isFinite(num)) {
throw new TypeError(`Expected a finite number, got ${typeof num}: ${num}`); throw new TypeError(`Expected a finite number, got ${typeof num}: ${num}`);
} }
@ -16,10 +16,10 @@ export const prettyBytes = (num: number) => {
} }
const exponent = Math.min( const exponent = Math.min(
Math.floor(Math.log(num) / Math.log(1000)), Math.floor(Math.log(num) / Math.log(step)),
UNITS.length - 1 UNITS.length - 1
); );
const numStr = Number((num / Math.pow(1000, exponent)).toPrecision(3)); const numStr = Number((num / Math.pow(step, exponent)).toPrecision(3));
const unit = UNITS[exponent]; const unit = UNITS[exponent];
return (neg ? '-' : '') + numStr + ' ' + unit; return (neg ? '-' : '') + numStr + ' ' + unit;

View File

@ -130,12 +130,13 @@ register('de-DE', {
'File.failed': 'Fehlerhafte Dateien', 'File.failed': 'Fehlerhafte Dateien',
'File.invalidType': '{{files}} entspricht nicht Typ `{{accept}}`', 'File.invalidType': '{{files}} entspricht nicht Typ `{{accept}}`',
'File.maxSize': 'File.maxSize':
'{{filename}} überschreitet die maximale Größe von {{maxsize}} (in Byte)', '{{filename}} überschreitet die maximale Größe von {{maxSize}}',
'File.pause': 'Hochladen anhalten', 'File.pause': 'Hochladen anhalten',
'File.repick': 'Erneut suswählen', 'File.repick': 'Erneut suswählen',
'File.result': 'File.result':
'Erfolgreich hochgeladene Dateien: {{uploaded}}, nicht hochgeladene Dateien: {{failed}}', 'Erfolgreich hochgeladene Dateien: {{uploaded}}, nicht hochgeladene Dateien: {{failed}}',
'File.retry': 'Wiederholen', 'File.retry': 'Wiederholen',
'File.sizeLimit': 'Die maximale Dateigröße ist {{maxSize}}',
'File.start': 'Hochladen beginnen', 'File.start': 'Hochladen beginnen',
'File.upload': 'Hochladen', 'File.upload': 'Hochladen',
'Image.upload': 'Hochladen', 'Image.upload': 'Hochladen',

View File

@ -128,13 +128,13 @@ register('en-US', {
'File.invalidType': '{{files}} does not match type `{{accept}}`', 'File.invalidType': '{{files}} does not match type `{{accept}}`',
'File.maxLength': 'The maximum limit is {{maxLength}}', 'File.maxLength': 'The maximum limit is {{maxLength}}',
'File.maxSize': 'File.maxSize':
'{{filename}} you selected exceeds the maximum limit of {{maxsize}} (in bytes)', '{{filename}} you selected exceeds the maximum limit of {{maxSize}}',
'File.pause': 'Pause uplaod', 'File.pause': 'Pause uplaod',
'File.repick': 'Repick', 'File.repick': 'Repick',
'File.result': 'File.result':
'Successfully uploaded {{uploaded}} files, failed to upload {{failed}} files', 'Successfully uploaded {{uploaded}} files, failed to upload {{failed}} files',
'File.retry': 'Retry', 'File.retry': 'Retry',
'File.sizeLimit': 'The maximum file size is {{maxSize}} B', 'File.sizeLimit': 'The maximum file size is {{maxSize}}',
'File.start': 'Start upload', 'File.start': 'Start upload',
'File.upload': 'Upload', 'File.upload': 'Upload',
'Image.upload': 'Upload image', 'Image.upload': 'Upload image',

View File

@ -133,12 +133,12 @@ register('zh-CN', {
'File.invalidType': '{{files}} 不符合类型的 {{accept}} 的设定,请仔细检查', 'File.invalidType': '{{files}} 不符合类型的 {{accept}} 的设定,请仔细检查',
'File.maxLength': '最多上传 {{maxLength}} 个文件', 'File.maxLength': '最多上传 {{maxLength}} 个文件',
'File.maxSize': 'File.maxSize':
'{{filename}} 大小为 {{actualSize}} 超出了最大为 {{maxSize}} (字节)的限制', '{{filename}} 大小为 {{actualSize}} 超出了最大为 {{maxSize}} 的限制',
'File.pause': '暂停上传', 'File.pause': '暂停上传',
'File.repick': '重新选择', 'File.repick': '重新选择',
'File.result': '已成功上传 {{uploaded}} 个文件,{{failed}} 个文件上传失败,', 'File.result': '已成功上传 {{uploaded}} 个文件,{{failed}} 个文件上传失败,',
'File.retry': '重试上传', 'File.retry': '重试上传',
'File.sizeLimit': '文件大小不超过 {{maxSize}} B', 'File.sizeLimit': '文件大小不超过 {{maxSize}}',
'File.start': '开始上传', 'File.start': '开始上传',
'File.upload': '文件上传', 'File.upload': '文件上传',
'Image.upload': '图片上传', 'Image.upload': '图片上传',

View File

@ -1,8 +1,7 @@
import React from 'react'; import React from 'react';
import {FormItem, FormControlProps, FormBaseControl} from 'amis-core'; import {FormItem, FormControlProps, prettyBytes} from 'amis-core';
import find from 'lodash/find'; import find from 'lodash/find';
import isPlainObject from 'lodash/isPlainObject'; import isPlainObject from 'lodash/isPlainObject';
import ImageControl from './InputImage';
import {Payload, ApiObject, ApiString, ActionObject} from 'amis-core'; import {Payload, ApiObject, ApiString, ActionObject} from 'amis-core';
import {qsstringify, createObject, guid, isEmpty} from 'amis-core'; import {qsstringify, createObject, guid, isEmpty} from 'amis-core';
import { import {
@ -21,8 +20,7 @@ import {
FormBaseControlSchema, FormBaseControlSchema,
SchemaApi, SchemaApi,
SchemaClassName, SchemaClassName,
SchemaTokenizeableString, SchemaTokenizeableString
SchemaUrlPath
} from '../../Schema'; } from '../../Schema';
import merge from 'lodash/merge'; import merge from 'lodash/merge';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@ -515,8 +513,8 @@ export default class FileControl extends React.Component<FileProps, FileState> {
// this.props.env.alert( // this.props.env.alert(
// __('File.maxSize', { // __('File.maxSize', {
// filename: file[nameField as keyof typeof file] || file.name, // filename: file[nameField as keyof typeof file] || file.name,
// actualSize: ImageControl.formatFileSize(file.size), // actualSize: prettyBytes(file.size),
// maxSize: ImageControl.formatFileSize(maxSize) // maxSize: prettyBytes(maxSize)
// }) // })
// ); // );
file.state = 'invalid'; file.state = 'invalid';
@ -1409,7 +1407,9 @@ export default class FileControl extends React.Component<FileProps, FileState> {
</div> </div>
{maxSize ? ( {maxSize ? (
<div className={cx('FileControl-sizeTip')}> <div className={cx('FileControl-sizeTip')}>
{__('File.sizeLimit', {maxSize})} {__('File.sizeLimit', {
maxSize: prettyBytes(maxSize, 1024)
})}
</div> </div>
) : null} ) : null}
</div> </div>
@ -1456,7 +1456,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
{maxSize && !drag ? ( {maxSize && !drag ? (
<div className={cx('FileControl-sizeTip')}> <div className={cx('FileControl-sizeTip')}>
{__('File.sizeLimit', {maxSize})} {__('File.sizeLimit', {maxSize: prettyBytes(maxSize, 1024)})}
</div> </div>
) : null} ) : null}
@ -1478,10 +1478,8 @@ export default class FileControl extends React.Component<FileProps, FileState> {
(maxSize && file.size > maxSize (maxSize && file.size > maxSize
? __('File.maxSize', { ? __('File.maxSize', {
filename: file.name, filename: file.name,
actualSize: ImageControl.formatFileSize( actualSize: prettyBytes(file.size, 1024),
file.size maxSize: prettyBytes(maxSize, 1024)
),
maxSize: ImageControl.formatFileSize(maxSize)
}) })
: '') : '')
: '' : ''

View File

@ -1,5 +1,10 @@
import React, {Suspense} from 'react'; import React, {Suspense} from 'react';
import {FormItem, FormControlProps, FormBaseControl} from 'amis-core'; import {
FormItem,
FormControlProps,
FormBaseControl,
prettyBytes
} from 'amis-core';
// import 'cropperjs/dist/cropper.css'; // import 'cropperjs/dist/cropper.css';
const Cropper = React.lazy(() => import('react-cropper')); const Cropper = React.lazy(() => import('react-cropper'));
import DropZone from 'react-dropzone'; import DropZone from 'react-dropzone';
@ -341,20 +346,6 @@ export default class ImageControl extends React.Component<
dropCrop: true dropCrop: true
}; };
static formatFileSize(
size: number | string,
units = [' B', ' KB', ' M', ' G']
) {
size = parseInt(size as string, 10) || 0;
while (size > 1024 && units.length > 1) {
size /= 1024;
units.shift();
}
return size.toFixed(2) + units[0];
}
static valueToFile( static valueToFile(
value: string | object, value: string | object,
props?: ImageProps props?: ImageProps
@ -997,8 +988,8 @@ export default class ImageControl extends React.Component<
this.props.env.alert( this.props.env.alert(
__('File.maxSize', { __('File.maxSize', {
filename: file.name, filename: file.name,
actualSize: ImageControl.formatFileSize(file.size), actualSize: prettyBytes(file.size, 1024),
maxSize: ImageControl.formatFileSize(maxSize) maxSize: prettyBytes(maxSize, 1024)
}) })
); );
return; return;
@ -1563,9 +1554,9 @@ export default class ImageControl extends React.Component<
</div>, </div>,
file.info.len ? ( file.info.len ? (
<div key="size"> <div key="size">
{ImageControl.formatFileSize( {prettyBytes(
file.info.len file.info.len
)} , 1024)}
</div> </div>
) : null ) : null
] ]