Web: Fixed the download and preview file not authorized. (#3652)

https://github.com/infiniflow/ragflow/issues/3651

### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
Fachuan Bai
2024-12-04 11:48:06 +08:00
committed by GitHub
parent efae7afd62
commit fc38afcec4
23 changed files with 1124 additions and 1034 deletions

View File

@ -1,8 +1,7 @@
import { useShowDeleteConfirm, useTranslate } from '@/hooks/common-hooks';
import { useRemoveNextDocument } from '@/hooks/document-hooks';
import { IDocumentInfo } from '@/interfaces/database/document';
import { api_host } from '@/utils/api';
import { downloadFile } from '@/utils/file-util';
import { downloadDocument } from '@/utils/file-util';
import {
DeleteOutlined,
DownloadOutlined,
@ -40,8 +39,8 @@ const ParsingActionCell = ({
};
const onDownloadDocument = () => {
downloadFile({
url: `${api_host}/document/get/${documentId}`,
downloadDocument({
id: documentId,
filename: record.name,
});
};

View File

@ -1,3 +1,5 @@
import { Authorization } from '@/constants/authorization';
import { getAuthorization } from '@/utils/authorization-util';
import jsPreviewExcel from '@js-preview/excel';
import axios from 'axios';
import mammoth from 'mammoth';
@ -23,7 +25,12 @@ export const useCatchError = (api: string) => {
export const useFetchDocument = () => {
const fetchDocument = useCallback(async (api: string) => {
const ret = await axios.get(api, { responseType: 'arraybuffer' });
const ret = await axios.get(api, {
headers: {
[Authorization]: getAuthorization(),
},
responseType: 'arraybuffer',
});
return ret;
}, []);
@ -64,30 +71,34 @@ export const useFetchExcel = (filePath: string) => {
export const useFetchDocx = (filePath: string) => {
const [succeed, setSucceed] = useState(true);
const [error, setError] = useState<string>();
const { fetchDocument } = useFetchDocument();
const containerRef = useRef<HTMLDivElement>(null);
const { error } = useCatchError(filePath);
const fetchDocumentAsync = useCallback(async () => {
const jsonFile = await fetchDocument(filePath);
mammoth
.convertToHtml(
{ arrayBuffer: jsonFile.data },
{ includeDefaultStyleMap: true },
)
.then((result) => {
setSucceed(true);
const docEl = document.createElement('div');
docEl.className = 'document-container';
docEl.innerHTML = result.value;
const container = containerRef.current;
if (container) {
container.innerHTML = docEl.outerHTML;
}
})
.catch(() => {
setSucceed(false);
});
try {
const jsonFile = await fetchDocument(filePath);
mammoth
.convertToHtml(
{ arrayBuffer: jsonFile.data },
{ includeDefaultStyleMap: true },
)
.then((result) => {
setSucceed(true);
const docEl = document.createElement('div');
docEl.className = 'document-container';
docEl.innerHTML = result.value;
const container = containerRef.current;
if (container) {
container.innerHTML = docEl.outerHTML;
}
})
.catch(() => {
setSucceed(false);
});
} catch (error: any) {
setError(error.toString());
}
}, [filePath, fetchDocument]);
useEffect(() => {

View File

@ -1,7 +1,14 @@
import { Authorization } from '@/constants/authorization';
import { getAuthorization } from '@/utils/authorization-util';
import { Skeleton } from 'antd';
import { PdfHighlighter, PdfLoader } from 'react-pdf-highlighter';
import FileError from '../file-error';
import { useCatchError } from '../hooks';
type PdfLoaderProps = React.ComponentProps<typeof PdfLoader> & {
httpHeaders?: Record<string, string>;
};
const Loader = PdfLoader as React.ComponentType<PdfLoaderProps>;
interface IProps {
url: string;
@ -10,11 +17,14 @@ interface IProps {
const PdfPreviewer = ({ url }: IProps) => {
const { error } = useCatchError(url);
const resetHash = () => {};
const httpHeaders = {
[Authorization]: getAuthorization(),
};
return (
<div style={{ width: '100%', height: '100%' }}>
<PdfLoader
<Loader
url={url}
httpHeaders={httpHeaders}
beforeLoad={<Skeleton active />}
workerSrc="/pdfjs-dist/pdf.worker.min.js"
errorMessage={<FileError>{error}</FileError>}
@ -37,7 +47,7 @@ const PdfPreviewer = ({ url }: IProps) => {
/>
);
}}
</PdfLoader>
</Loader>
</div>
);
};

View File

@ -1,13 +1,12 @@
import NewDocumentLink from '@/components/new-document-link';
import SvgIcon from '@/components/svg-icon';
import { useTranslate } from '@/hooks/common-hooks';
import { useDownloadFile } from '@/hooks/file-manager-hooks';
import { IFile } from '@/interfaces/database/file-manager';
import { api_host } from '@/utils/api';
import {
getExtension,
isSupportedPreviewDocumentType,
} from '@/utils/document-util';
import { downloadFile } from '@/utils/file-util';
import {
DeleteOutlined,
DownloadOutlined,
@ -42,12 +41,13 @@ const ActionCell = ({
[documentId],
setSelectedRowKeys,
);
const { downloadFile, loading } = useDownloadFile();
const extension = getExtension(record.name);
const isKnowledgeBase = record.source_type === 'knowledgebase';
const onDownloadDocument = () => {
downloadFile({
url: `${api_host}/file/get/${documentId}`,
id: documentId,
filename: record.name,
});
};
@ -106,7 +106,12 @@ const ActionCell = ({
)}
{record.type !== 'folder' && (
<Tooltip title={t('download', { keyPrefix: 'common' })}>
<Button type="text" disabled={beingUsed} onClick={onDownloadDocument}>
<Button
type="text"
disabled={beingUsed}
loading={loading}
onClick={onDownloadDocument}
>
<DownloadOutlined size={20} />
</Button>
</Tooltip>

View File

@ -27,7 +27,7 @@
.titleWrapper {
margin: 16px 0;
overflow: hidden;
.title {
display: -webkit-box;
-webkit-line-clamp: 2;
@ -39,8 +39,8 @@
color: rgba(0, 0, 0, 0.88);
word-break: break-all;
}
.description{
.description {
margin-top: 4px;
display: -webkit-box;
-webkit-line-clamp: 3;

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Flex, Form, Input, Modal, Select, Space, InputNumber } from 'antd';
import { Flex, Form, Input, Modal, Select, Space } from 'antd';
import omit from 'lodash/omit';
type FieldType = IAddLlmRequestBody & {
@ -30,7 +30,7 @@ const TencentCloudModal = ({
...omit(values),
model_type: modelType,
llm_factory: llmFactory,
max_tokens:16000,
max_tokens: 16000,
};
console.info(data);

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Form, Input, Modal, Select, Switch, InputNumber } from 'antd';
import { Form, Input, InputNumber, Modal, Select, Switch } from 'antd';
import omit from 'lodash/omit';
type FieldType = IAddLlmRequestBody & {
@ -33,7 +33,7 @@ const AzureOpenAIModal = ({
...omit(values, ['vision']),
model_type: modelType,
llm_factory: llmFactory,
max_tokens:values.max_tokens,
max_tokens: values.max_tokens,
};
console.info(data);

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Flex, Form, Input, Modal, Select, Space, InputNumber } from 'antd';
import { Flex, Form, Input, InputNumber, Modal, Select, Space } from 'antd';
import { useMemo } from 'react';
import { BedrockRegionList } from '../constant';
@ -34,7 +34,7 @@ const BedrockModal = ({
const data = {
...values,
llm_factory: llmFactory,
max_tokens:values.max_tokens,
max_tokens: values.max_tokens,
};
onOk?.(data);
@ -136,7 +136,6 @@ const BedrockModal = ({
style={{ width: '100%' }}
/>
</Form.Item>
</Form>
</Modal>
);

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Flex, Form, Input, Modal, Select, Space, InputNumber } from 'antd';
import { Flex, Form, Input, InputNumber, Modal, Select, Space } from 'antd';
import omit from 'lodash/omit';
type FieldType = IAddLlmRequestBody & {
@ -30,7 +30,7 @@ const FishAudioModal = ({
...omit(values),
model_type: modelType,
llm_factory: llmFactory,
max_tokens:values.max_tokens,
max_tokens: values.max_tokens,
};
console.info(data);
@ -118,7 +118,6 @@ const FishAudioModal = ({
style={{ width: '100%' }}
/>
</Form.Item>
</Form>
</Modal>
);

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Form, Input, Modal, Select, InputNumber } from 'antd';
import { Form, Input, InputNumber, Modal, Select } from 'antd';
type FieldType = IAddLlmRequestBody & {
google_project_id: string;
@ -27,7 +27,7 @@ const GoogleModal = ({
const data = {
...values,
llm_factory: llmFactory,
max_tokens:values.max_tokens,
max_tokens: values.max_tokens,
};
onOk?.(data);
@ -112,7 +112,6 @@ const GoogleModal = ({
style={{ width: '100%' }}
/>
</Form.Item>
</Form>
</Modal>
);

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Form, Input, Modal, Select} from 'antd';
import { Form, Input, Modal, Select } from 'antd';
import omit from 'lodash/omit';
type FieldType = IAddLlmRequestBody & {

View File

@ -1,7 +1,16 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Flex, Form, Input, Modal, Select, Space, Switch, InputNumber } from 'antd';
import {
Flex,
Form,
Input,
InputNumber,
Modal,
Select,
Space,
Switch,
} from 'antd';
import omit from 'lodash/omit';
type FieldType = IAddLlmRequestBody & { vision: boolean };
@ -45,7 +54,7 @@ const OllamaModal = ({
...omit(values, ['vision']),
model_type: modelType,
llm_factory: llmFactory,
max_tokens:values.max_tokens,
max_tokens: values.max_tokens,
};
console.info(data);

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Form, Input, Modal, Select, InputNumber } from 'antd';
import { Form, Input, InputNumber, Modal, Select } from 'antd';
import omit from 'lodash/omit';
type FieldType = IAddLlmRequestBody & {
@ -36,7 +36,7 @@ const SparkModal = ({
...omit(values, ['vision']),
model_type: modelType,
llm_factory: llmFactory,
max_tokens:values.max_tokens,
max_tokens: values.max_tokens,
};
console.info(data);
@ -80,52 +80,56 @@ const SparkModal = ({
<Form.Item noStyle dependencies={['model_type']}>
{({ getFieldValue }) =>
getFieldValue('model_type') === 'chat' && (
<Form.Item<FieldType>
label={t('addSparkAPIPassword')}
name="spark_api_password"
rules={[{ required: true, message: t('SparkAPIPasswordMessage') }]}
>
<Input placeholder={t('SparkAPIPasswordMessage')} />
</Form.Item>
<Form.Item<FieldType>
label={t('addSparkAPIPassword')}
name="spark_api_password"
rules={[
{ required: true, message: t('SparkAPIPasswordMessage') },
]}
>
<Input placeholder={t('SparkAPIPasswordMessage')} />
</Form.Item>
)
}
</Form.Item>
<Form.Item noStyle dependencies={['model_type']}>
{({ getFieldValue }) =>
getFieldValue('model_type') === 'tts' && (
<Form.Item<FieldType>
label={t('addSparkAPPID')}
name="spark_app_id"
rules={[{ required: true, message: t('SparkAPPIDMessage') }]}
>
<Input placeholder={t('SparkAPPIDMessage')} />
</Form.Item>
<Form.Item<FieldType>
label={t('addSparkAPPID')}
name="spark_app_id"
rules={[{ required: true, message: t('SparkAPPIDMessage') }]}
>
<Input placeholder={t('SparkAPPIDMessage')} />
</Form.Item>
)
}
</Form.Item>
<Form.Item noStyle dependencies={['model_type']}>
{({ getFieldValue }) =>
getFieldValue('model_type') === 'tts' && (
<Form.Item<FieldType>
label={t('addSparkAPISecret')}
name="spark_api_secret"
rules={[{ required: true, message: t('SparkAPISecretMessage') }]}
>
<Input placeholder={t('SparkAPISecretMessage')} />
</Form.Item>
<Form.Item<FieldType>
label={t('addSparkAPISecret')}
name="spark_api_secret"
rules={[
{ required: true, message: t('SparkAPISecretMessage') },
]}
>
<Input placeholder={t('SparkAPISecretMessage')} />
</Form.Item>
)
}
</Form.Item>
<Form.Item noStyle dependencies={['model_type']}>
{({ getFieldValue }) =>
getFieldValue('model_type') === 'tts' && (
<Form.Item<FieldType>
label={t('addSparkAPIKey')}
name="spark_api_key"
rules={[{ required: true, message: t('SparkAPIKeyMessage') }]}
>
<Input placeholder={t('SparkAPIKeyMessage')} />
</Form.Item>
<Form.Item<FieldType>
label={t('addSparkAPIKey')}
name="spark_api_key"
rules={[{ required: true, message: t('SparkAPIKeyMessage') }]}
>
<Input placeholder={t('SparkAPIKeyMessage')} />
</Form.Item>
)
}
</Form.Item>
@ -153,7 +157,6 @@ const SparkModal = ({
style={{ width: '100%' }}
/>
</Form.Item>
</Form>
</Modal>
);

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Flex, Form, Input, Modal, Select, Space, Switch, InputNumber } from 'antd';
import { Flex, Form, Input, InputNumber, Modal, Select, Space } from 'antd';
import omit from 'lodash/omit';
type FieldType = IAddLlmRequestBody & {
@ -36,7 +36,7 @@ const VolcEngineModal = ({
...omit(values, ['vision']),
model_type: modelType,
llm_factory: llmFactory,
max_tokens:values.max_tokens,
max_tokens: values.max_tokens,
};
console.info(data);
@ -128,7 +128,6 @@ const VolcEngineModal = ({
style={{ width: '100%' }}
/>
</Form.Item>
</Form>
</Modal>
);

View File

@ -1,7 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
import { Form, Input, Modal, Select, InputNumber } from 'antd';
import { Form, Input, InputNumber, Modal, Select } from 'antd';
import omit from 'lodash/omit';
type FieldType = IAddLlmRequestBody & {
@ -34,7 +34,7 @@ const YiyanModal = ({
...omit(values, ['vision']),
model_type: modelType,
llm_factory: llmFactory,
max_tokens:values.max_tokens,
max_tokens: values.max_tokens,
};
console.info(data);