内部自动转 form-data 如果存在文件
This commit is contained in:
parent
a69b8211f4
commit
ecb4d8a51f
|
@ -89,32 +89,9 @@ export default function(schema) {
|
||||||
data,
|
data,
|
||||||
config
|
config
|
||||||
}) => {
|
}) => {
|
||||||
let hasFile = function(data) {
|
|
||||||
return Object.keys(data).some(key => {
|
|
||||||
let value = data[key];
|
|
||||||
|
|
||||||
return value instanceof File || Array.isArray(value) && value.length && value[0] instanceof File;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data && data instanceof FormData) {
|
if (data && data instanceof FormData) {
|
||||||
// config.headers = config.headers || {};
|
// config.headers = config.headers || {};
|
||||||
// config.headers['Content-Type'] = 'multipart/form-data';
|
// config.headers['Content-Type'] = 'multipart/form-data';
|
||||||
} else if (hasFile(data)) {
|
|
||||||
const fd = new FormData();
|
|
||||||
Object.keys(data).forEach(key => {
|
|
||||||
const value = data[key];
|
|
||||||
|
|
||||||
if (value instanceof File) {
|
|
||||||
fd.append(key, value, value.name);
|
|
||||||
} else if (Array.isArray(value) && value.length && value[0] instanceof File) {
|
|
||||||
value.forEach(value => fd.append(`${key}[]`, value, value.name));
|
|
||||||
} else {
|
|
||||||
// todo 复杂对象还需要特殊处理。
|
|
||||||
fd.append(key, value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
data = fd;
|
|
||||||
} else if (data
|
} else if (data
|
||||||
&& typeof data !== 'string'
|
&& typeof data !== 'string'
|
||||||
&& !(data instanceof Blob)
|
&& !(data instanceof Blob)
|
||||||
|
|
|
@ -638,6 +638,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
|
||||||
className="text-danger pull-right"
|
className="text-danger pull-right"
|
||||||
onClick={() => this.removeFile(file, key)}
|
onClick={() => this.removeFile(file, key)}
|
||||||
href="javascript:void 0"
|
href="javascript:void 0"
|
||||||
|
data-tooltip="移除"
|
||||||
><i className="fa fa-times" /></a>
|
><i className="fa fa-times" /></a>
|
||||||
<span className="pull-right text-muted text-xs m-r-sm">{stateTextMap && stateTextMap[file.state as string] || ''}</span>
|
<span className="pull-right text-muted text-xs m-r-sm">{stateTextMap && stateTextMap[file.state as string] || ''}</span>
|
||||||
<i className="fa fa-file fa-fw m-r-xs" />
|
<i className="fa fa-file fa-fw m-r-xs" />
|
||||||
|
|
|
@ -12,6 +12,8 @@ export interface ApiObject {
|
||||||
adaptor?: (payload: object, response: fetcherResult, api: ApiObject) => any;
|
adaptor?: (payload: object, response: fetcherResult, api: ApiObject) => any;
|
||||||
requestAdaptor?: (api: ApiObject) => ApiObject;
|
requestAdaptor?: (api: ApiObject) => ApiObject;
|
||||||
cache?: number;
|
cache?: number;
|
||||||
|
qsOptions?: any;
|
||||||
|
dataType?: 'json' | 'form-data'
|
||||||
};
|
};
|
||||||
export type ApiString = string;
|
export type ApiString = string;
|
||||||
export type Api = ApiString | ApiObject;
|
export type Api = ApiString | ApiObject;
|
||||||
|
|
|
@ -16,7 +16,9 @@ import qs from 'qs';
|
||||||
import { evalExpression } from './tpl';
|
import { evalExpression } from './tpl';
|
||||||
import {
|
import {
|
||||||
isObject,
|
isObject,
|
||||||
isObjectShallowModified
|
isObjectShallowModified,
|
||||||
|
hasFile,
|
||||||
|
object2formData
|
||||||
} from './helper';
|
} from './helper';
|
||||||
|
|
||||||
interface ApiCacheConfig extends ApiObject {
|
interface ApiCacheConfig extends ApiObject {
|
||||||
|
@ -121,6 +123,11 @@ function responseAdaptor(ret: fetcherResult) {
|
||||||
export function wrapFetcher(fn: (config: fetcherConfig) => Promise<fetcherResult>): (api: Api, data: object, options?: object) => Promise<Payload | void> {
|
export function wrapFetcher(fn: (config: fetcherConfig) => Promise<fetcherResult>): (api: Api, data: object, options?: object) => Promise<Payload | void> {
|
||||||
return function (api, data, options) {
|
return function (api, data, options) {
|
||||||
api = buildApi(api, data, options) as ApiObject;
|
api = buildApi(api, data, options) as ApiObject;
|
||||||
|
|
||||||
|
if (api.data && (hasFile(api.data) || api.dataType === 'form-data')) {
|
||||||
|
api.data = object2formData(api.data, api.qsOptions);
|
||||||
|
}
|
||||||
|
|
||||||
api.requestAdaptor && (api = api.requestAdaptor(api) || api);
|
api.requestAdaptor && (api = api.requestAdaptor(api) || api);
|
||||||
|
|
||||||
if (typeof api.cache === 'number' && api.cache > 0) {
|
if (typeof api.cache === 'number' && api.cache > 0) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { evalExpression } from './tpl';
|
import { evalExpression } from './tpl';
|
||||||
import { boundMethod } from 'autobind-decorator';
|
import { boundMethod } from 'autobind-decorator';
|
||||||
|
import qs from 'qs';
|
||||||
|
|
||||||
// 方便取值的时候能够把上层的取到,但是获取的时候不会全部把所有的数据获取到。
|
// 方便取值的时候能够把上层的取到,但是获取的时候不会全部把所有的数据获取到。
|
||||||
export function createObject(superProps?: { [propName: string]: any }, props?: { [propName: string]: any }, properties?: any): object {
|
export function createObject(superProps?: { [propName: string]: any }, props?: { [propName: string]: any }, properties?: any): object {
|
||||||
|
@ -657,4 +658,38 @@ export function sortArray<T extends any>(items:Array<T>, field:string, dir: -1 |
|
||||||
|
|
||||||
return ret * dir;
|
return ret * dir;
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只判断一层, 如果层级很深,form-data 也不好表达。
|
||||||
|
export function hasFile(object:any):boolean {
|
||||||
|
return Object.keys(object).some(key => {
|
||||||
|
let value = object[key];
|
||||||
|
|
||||||
|
return value instanceof File || Array.isArray(value) && value.length && value[0] instanceof File;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function object2formData(data:any, options:any = {
|
||||||
|
arrayForamt: 'brackets'
|
||||||
|
}):any {
|
||||||
|
let others:any = {};
|
||||||
|
const fd = new FormData();
|
||||||
|
Object.keys(data).forEach(key => {
|
||||||
|
const value = data[key];
|
||||||
|
|
||||||
|
if (value instanceof File) {
|
||||||
|
fd.append(key, value, value.name);
|
||||||
|
} else if (Array.isArray(value) && value.length && value[0] instanceof File) {
|
||||||
|
value.forEach(value => fd.append(`${key}[]`, value, value.name));
|
||||||
|
} else {
|
||||||
|
others[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 因为 key 的格式太多了,偷个懒,用 qs 来处理吧。
|
||||||
|
qs.stringify(others, options).split('&').forEach(item => {
|
||||||
|
let parts = item.split('=');
|
||||||
|
parts[0] && fd.append(parts[0], parts[1]);
|
||||||
|
});
|
||||||
|
return fd;
|
||||||
}
|
}
|
Loading…
Reference in New Issue