mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
parent
b025e69e3d
commit
59d900ffd5
@ -333,6 +333,8 @@ icon 也可以是 url 地址,比如
|
||||
|
||||
通过配置 `"actionType":"download"` 和 `api`,可以实现下载请求,它其实是 `ajax` 的一种特例,自动给 api 加上了 `"responseType": "blob"`。
|
||||
|
||||
> 3.5.0 版本开始可以配置 `downloadFileName` 来覆盖下载文件名。注意:即便配置了 `downloadFileName`,api 依然需要返回 `Content-Disposition` 头。
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"label": "下载",
|
||||
|
@ -199,7 +199,7 @@ export default class PlayGround extends React.Component {
|
||||
};
|
||||
|
||||
let response = await axios(config);
|
||||
response = await attachmentAdpator(response, __);
|
||||
response = await attachmentAdpator(response, __, api);
|
||||
|
||||
if (response.status >= 400) {
|
||||
if (response.data) {
|
||||
|
@ -213,7 +213,7 @@ export function embed(
|
||||
let response = config.mockResponse
|
||||
? config.mockResponse
|
||||
: await axios(config);
|
||||
response = await attachmentAdpator(response, __);
|
||||
response = await attachmentAdpator(response, __, api);
|
||||
response = responseAdaptor(api)(response);
|
||||
|
||||
if (response.status >= 400) {
|
||||
|
@ -230,6 +230,7 @@ export interface ApiObject extends BaseApiObject {
|
||||
) => ApiObject | Promise<ApiObject>;
|
||||
/** 是否过滤为空字符串的 query 参数 */
|
||||
filterEmptyQuery?: boolean;
|
||||
downloadFileName?: string;
|
||||
}
|
||||
export type ApiString = string;
|
||||
export type Api = ApiString | ApiObject;
|
||||
|
@ -5,24 +5,35 @@
|
||||
* @returns
|
||||
*/
|
||||
|
||||
export function attachmentAdpator(response: any, __: Function) {
|
||||
import {ApiObject} from '../types';
|
||||
|
||||
export function attachmentAdpator(
|
||||
response: any,
|
||||
__: Function,
|
||||
api?: ApiObject
|
||||
) {
|
||||
if (response && response.headers && response.headers['content-disposition']) {
|
||||
const disposition = response.headers['content-disposition'];
|
||||
let filename = '';
|
||||
|
||||
if (disposition && disposition.indexOf('attachment') !== -1) {
|
||||
// disposition 有可能是 attachment; filename="??.xlsx"; filename*=UTF-8''%E4%B8%AD%E6%96%87.xlsx
|
||||
// 这种情况下最后一个才是正确的文件名
|
||||
let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
|
||||
// 如果 api 中配置了,则优先用 api 中的配置
|
||||
if (api?.downloadFileName) {
|
||||
filename = api.downloadFileName;
|
||||
} else {
|
||||
// disposition 有可能是 attachment; filename="??.xlsx"; filename*=UTF-8''%E4%B8%AD%E6%96%87.xlsx
|
||||
// 这种情况下最后一个才是正确的文件名
|
||||
let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/i;
|
||||
|
||||
let matches = disposition.match(filenameRegex);
|
||||
if (matches && matches.length) {
|
||||
filename = matches[1].replace(`UTF-8''`, '').replace(/['"]/g, '');
|
||||
}
|
||||
let matches = disposition.match(filenameRegex);
|
||||
if (matches && matches.length) {
|
||||
filename = matches[1].replace(`UTF-8''`, '').replace(/['"]/g, '');
|
||||
}
|
||||
|
||||
// 很可能是中文被 url-encode 了
|
||||
if (filename && filename.replace(/[^%]/g, '').length > 2) {
|
||||
filename = decodeURIComponent(filename);
|
||||
// 很可能是中文被 url-encode 了
|
||||
if (filename && filename.replace(/[^%]/g, '').length > 2) {
|
||||
filename = decodeURIComponent(filename);
|
||||
}
|
||||
}
|
||||
|
||||
let type = response.headers['content-type'];
|
||||
|
@ -33,6 +33,7 @@ export function handleAction(
|
||||
action.actionType = 'ajax';
|
||||
const api = normalizeApi((action as any).api);
|
||||
api.responseType = 'blob';
|
||||
api.downloadFileName = action.downloadFileName;
|
||||
(action as any).api = api;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,8 @@ export const env: RenderOptions = {
|
||||
jumpTo: () => {
|
||||
toast.info('温馨提示:预览模式下禁止跳转');
|
||||
},
|
||||
fetcher: async ({url, method, data, config, headers}: any) => {
|
||||
fetcher: async (api: any) => {
|
||||
let {url, method, data, config, headers} = api;
|
||||
config = config || {};
|
||||
config.url = url;
|
||||
config.withCredentials = true;
|
||||
@ -40,7 +41,7 @@ export const env: RenderOptions = {
|
||||
}
|
||||
|
||||
let response = await axios(config);
|
||||
response = await attachmentAdpator(response, (msg: string) => '');
|
||||
response = await attachmentAdpator(response, (msg: string) => msg, api);
|
||||
return response;
|
||||
},
|
||||
isCancel: (value: any) => (axios as any).isCancel(value),
|
||||
|
@ -617,6 +617,11 @@ export interface SchemaApiObject {
|
||||
* autoFill 是否显示自动填充错误提示
|
||||
*/
|
||||
silent?: boolean;
|
||||
|
||||
/**
|
||||
* 文件下载时,指定文件名
|
||||
*/
|
||||
downloadFileName?: string;
|
||||
}
|
||||
|
||||
export type SchemaApi = string | SchemaApiObject;
|
||||
|
@ -198,6 +198,7 @@ export interface DownloadActionSchema
|
||||
* 指定为下载行为
|
||||
*/
|
||||
actionType: 'download';
|
||||
downloadFileName?: string;
|
||||
}
|
||||
|
||||
export interface SaveAsActionSchema
|
||||
@ -362,6 +363,7 @@ export interface OtherActionSchema extends ButtonSchema {
|
||||
|
||||
export interface VanillaAction extends ButtonSchema {
|
||||
actionType?: string;
|
||||
downloadFileName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -426,7 +428,8 @@ const ActionProps = [
|
||||
'requireSelected',
|
||||
'countDown',
|
||||
'fileName',
|
||||
'isolateScope'
|
||||
'isolateScope',
|
||||
'downloadFileName'
|
||||
];
|
||||
import {filterContents} from './Remark';
|
||||
import {ClassNamesFn, themeable, ThemeProps} from 'amis-core';
|
||||
@ -624,6 +627,7 @@ export class Action extends React.Component<ActionProps, ActionState> {
|
||||
action.actionType = 'ajax';
|
||||
const api = normalizeApi((action as AjaxActionSchema).api);
|
||||
api.responseType = 'blob';
|
||||
api.downloadFileName = action.downloadFileName;
|
||||
(action as AjaxActionSchema).api = api;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user