diff --git a/app/src/asset/anno.ts b/app/src/asset/anno.ts
index cad1fa580..b70afeaf0 100644
--- a/app/src/asset/anno.ts
+++ b/app/src/asset/anno.ts
@@ -8,6 +8,8 @@ import {Constants} from "../constants";
import {Dialog} from "../dialog";
import {showMessage} from "../dialog/message";
import {isMobile} from "../util/functions";
+import {confirmDialog} from "../dialog/confirmDialog";
+import prettyBytes from "pretty-bytes";
export const initAnno = (element: HTMLElement, pdf: any) => {
getConfig(pdf);
@@ -738,13 +740,19 @@ const copyAnno = (idPath: string, fileName: string, pdf: any) => {
fetch(imageDataURL).then((response) => {
return response.blob();
}).then((blob) => {
- const formData = new FormData();
const imageName = content + ".png";
- formData.append("file[]", blob, imageName);
- formData.append("skipIfDuplicated", "true");
- fetchPost(Constants.UPLOAD_ADDRESS, formData, (response) => {
- writeText(`<<${idPath} "${content}">>
+ let msg = "";
+ if (Constants.SIZE_UPLOAD_TIP_SIZE <= blob.size) {
+ msg = window.siyuan.languages.uploadFileTooLarge.replace("${x}", imageName).replace("${y}", prettyBytes(blob.size, {binary: true}));
+ }
+ confirmDialog(msg ? window.siyuan.languages.upload : "", msg, () => {
+ const formData = new FormData();
+ formData.append("file[]", blob, imageName);
+ formData.append("skipIfDuplicated", "true");
+ fetchPost(Constants.UPLOAD_ADDRESS, formData, (response) => {
+ writeText(`<<${idPath} "${content}">>
`);
+ });
});
});
});
diff --git a/app/src/constants.ts b/app/src/constants.ts
index a5154561b..d14997e76 100644
--- a/app/src/constants.ts
+++ b/app/src/constants.ts
@@ -67,6 +67,7 @@ export abstract class Constants {
// size
public static readonly SIZE_DATABASE_MAZ_SIZE: number = 102400;
+ public static readonly SIZE_UPLOAD_TIP_SIZE: number = 256 * 1024 * 1024;
public static readonly SIZE_SCROLL_TB: number = 24;
public static readonly SIZE_SCROLL_STEP: number = 256;
public static readonly SIZE_LINK_TEXT_MAX: number = 64;
diff --git a/app/src/protyle/render/av/asset.ts b/app/src/protyle/render/av/asset.ts
index db0dd4155..9955b475a 100644
--- a/app/src/protyle/render/av/asset.ts
+++ b/app/src/protyle/render/av/asset.ts
@@ -22,6 +22,8 @@ import * as dayjs from "dayjs";
import {getColId} from "./col";
import {getFieldIdByCellElement} from "./row";
import {getCompressURL, removeCompressURL} from "../../../util/image";
+import {confirmDialog} from "../../../dialog/confirmDialog";
+import prettyBytes from "pretty-bytes";
export const bindAssetEvent = (options: {
protyle: IProtyle,
@@ -420,40 +422,51 @@ ${window.siyuan.languages.title}
menu.element.querySelector("textarea").focus();
};
-export const dragUpload = (files: string[], protyle: IProtyle, cellElement: HTMLElement) => {
- const msgId = showMessage(window.siyuan.languages.uploading, 0);
- fetchPost("/api/asset/insertLocalAssets", {
- assetPaths: files,
- isUpload: true,
- id: protyle.block.rootID
- }, (response) => {
- const blockElement = hasClosestBlock(cellElement);
- if (blockElement) {
- hideMessage(msgId);
- const addValue: IAVCellAssetValue[] = [];
- Object.keys(response.data.succMap).forEach(key => {
- const type = pathPosix().extname(key).toLowerCase();
- const name = key.substring(0, key.length - type.length);
- if (Constants.SIYUAN_ASSETS_IMAGE.includes(type)) {
- addValue.push({
- type: "image",
- name,
- content: response.data.succMap[key],
- });
- } else {
- addValue.push({
- type: "file",
- name,
- content: response.data.succMap[key],
- });
- }
- });
- updateAssetCell({
- protyle,
- blockElement,
- cellElements: [cellElement],
- addValue
- });
+export const dragUpload = (files: ILocalFiles[], protyle: IProtyle, cellElement: HTMLElement) => {
+ let msg = "";
+ const assetPaths: string[] = [];
+ files.forEach(item => {
+ if (item.size && Constants.SIZE_UPLOAD_TIP_SIZE <= item.size) {
+ msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", item.path).replace("${y}", prettyBytes(item.size, {binary: true})) + "
";
}
+ assetPaths.push(item.path);
+ });
+
+ confirmDialog(msg ? window.siyuan.languages.upload : "", msg, () => {
+ const msgId = showMessage(window.siyuan.languages.uploading, 0);
+ fetchPost("/api/asset/insertLocalAssets", {
+ assetPaths,
+ isUpload: true,
+ id: protyle.block.rootID
+ }, (response) => {
+ const blockElement = hasClosestBlock(cellElement);
+ if (blockElement) {
+ hideMessage(msgId);
+ const addValue: IAVCellAssetValue[] = [];
+ Object.keys(response.data.succMap).forEach(key => {
+ const type = pathPosix().extname(key).toLowerCase();
+ const name = key.substring(0, key.length - type.length);
+ if (Constants.SIYUAN_ASSETS_IMAGE.includes(type)) {
+ addValue.push({
+ type: "image",
+ name,
+ content: response.data.succMap[key],
+ });
+ } else {
+ addValue.push({
+ type: "file",
+ name,
+ content: response.data.succMap[key],
+ });
+ }
+ });
+ updateAssetCell({
+ protyle,
+ blockElement,
+ cellElements: [cellElement],
+ addValue
+ });
+ }
+ });
});
};
diff --git a/app/src/protyle/render/av/blockAttr.ts b/app/src/protyle/render/av/blockAttr.ts
index 58920931e..5bc73d0f4 100644
--- a/app/src/protyle/render/av/blockAttr.ts
+++ b/app/src/protyle/render/av/blockAttr.ts
@@ -275,9 +275,12 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"]
const cellElement = element.querySelector(".custom-attr__avvalue--active") as HTMLElement;
if (cellElement) {
if (event.dataTransfer.types[0] === "Files" && !isBrowser()) {
- const files: string[] = [];
+ const files: ILocalFiles[] = [];
for (let i = 0; i < event.dataTransfer.files.length; i++) {
- files.push(webUtils.getPathForFile(event.dataTransfer.files[i]));
+ files.push({
+ path: webUtils.getPathForFile(event.dataTransfer.files[i]),
+ size: event.dataTransfer.files[i].size
+ });
}
dragUpload(files, protyle, cellElement);
}
diff --git a/app/src/protyle/upload/index.ts b/app/src/protyle/upload/index.ts
index 0925c382e..67ab33161 100644
--- a/app/src/protyle/upload/index.ts
+++ b/app/src/protyle/upload/index.ts
@@ -10,6 +10,8 @@ import {hasClosestBlock} from "../util/hasClosest";
import {getContenteditableElement} from "../wysiwyg/getBlock";
import {getTypeByCellElement, updateCellsValue} from "../render/av/cell";
import {scrollCenter} from "../../util/highlightById";
+import {confirmDialog} from "../../dialog/confirmDialog";
+import prettyBytes from "pretty-bytes";
interface FileWithPath extends File {
path: string;
@@ -213,53 +215,39 @@ const genUploadedLabel = (responseText: string, protyle: IProtyle) => {
}, hasImage ? 0 : Constants.TIMEOUT_LOAD);
};
-export const uploadLocalFiles = (files: string[], protyle: IProtyle, isUpload: boolean) => {
- const msgId = showMessage(window.siyuan.languages.uploading, 0);
- fetchPost("/api/asset/insertLocalAssets", {
- assetPaths: files,
- isUpload,
- id: protyle.block.rootID
- }, (response) => {
- hideMessage(msgId);
- let tip = "";
- Object.keys(response.data.succMap).forEach(name => {
- if (response.data.succMap[name].startsWith("file:")) {
- tip += name + ", ";
- }
- });
- if (tip) {
- showMessage(window.siyuan.languages.dndFolderTip.replace("${x}", `${tip.substring(0, tip.length - 2)}`));
+export const uploadLocalFiles = (files: ILocalFiles[], protyle: IProtyle, isUpload: boolean) => {
+ let msg = "";
+ const assetPaths: string[] = [];
+ files.forEach(item => {
+ if (item.size && Constants.SIZE_UPLOAD_TIP_SIZE <= item.size) {
+ msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", item.path).replace("${y}", prettyBytes(item.size, {binary: true})) + "
";
}
- genUploadedLabel(JSON.stringify(response), protyle);
+ assetPaths.push(item.path);
+ });
+
+ confirmDialog(msg ? window.siyuan.languages.upload : "", msg, () => {
+ const msgId = showMessage(window.siyuan.languages.uploading, 0);
+ fetchPost("/api/asset/insertLocalAssets", {
+ assetPaths,
+ isUpload,
+ id: protyle.block.rootID
+ }, (response) => {
+ hideMessage(msgId);
+ let tip = "";
+ Object.keys(response.data.succMap).forEach(name => {
+ if (response.data.succMap[name].startsWith("file:")) {
+ tip += name + ", ";
+ }
+ });
+ if (tip) {
+ showMessage(window.siyuan.languages.dndFolderTip.replace("${x}", `${tip.substring(0, tip.length - 2)}`));
+ }
+ genUploadedLabel(JSON.stringify(response), protyle);
+ });
});
};
export const uploadFiles = (protyle: IProtyle, files: FileList | DataTransferItemList | File[], element?: HTMLInputElement, successCB?: (res: string) => void) => {
- // 文档书中点开属性->数据库后的变更操作
- if (!protyle) {
- const formData = new FormData();
- for (let i = 0, iMax = files.length; i < iMax; i++) {
- formData.append("file[]", files[i] as File);
- }
- const xhr = new XMLHttpRequest();
- xhr.open("POST", Constants.UPLOAD_ADDRESS);
- xhr.onreadystatechange = () => {
- if (xhr.readyState === XMLHttpRequest.DONE) {
- if (xhr.status === 200) {
- successCB(xhr.responseText);
- } else if (xhr.status === 0) {
- showMessage(window.siyuan.languages.fileTypeError);
- } else {
- showMessage(xhr.responseText);
- }
- if (element) {
- element.value = "";
- }
- }
- };
- xhr.send(formData);
- return;
- }
// FileList | DataTransferItemList | File[] => File[]
let fileList = [];
for (let i = 0; i < files.length; i++) {
@@ -269,7 +257,7 @@ export const uploadFiles = (protyle: IProtyle, files: FileList | DataTransferIte
}
if (0 === fileItem.size && "" === fileItem.type && -1 === fileItem.name.indexOf(".")) {
// 文件夹
- uploadLocalFiles([(fileItem as FileWithPath).path], protyle, false);
+ uploadLocalFiles([{path: (fileItem as FileWithPath).path, size: null}], protyle, false);
} else {
fileList.push(fileItem);
}
@@ -319,65 +307,71 @@ export const uploadFiles = (protyle: IProtyle, files: FileList | DataTransferIte
for (const key of Object.keys(extraData)) {
formData.append(key, extraData[key]);
}
-
+ let msg = "";
for (let i = 0, iMax = validateResult.files.length; i < iMax; i++) {
formData.append(protyle.options.upload.fieldName, validateResult.files[i]);
- }
- formData.append("id", protyle.block.rootID);
- const xhr = new XMLHttpRequest();
- xhr.open("POST", protyle.options.upload.url);
- if (protyle.options.upload.token) {
- xhr.setRequestHeader("X-Upload-Token", protyle.options.upload.token);
- }
- if (protyle.options.upload.withCredentials) {
- xhr.withCredentials = true;
+ if (Constants.SIZE_UPLOAD_TIP_SIZE <= validateResult.files[i].size) {
+ msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", validateResult.files[i].name).replace("${y}", prettyBytes(validateResult.files[i].size, {binary: true})) + "
";
+ }
}
- protyle.upload.isUploading = true;
- xhr.onreadystatechange = () => {
- if (xhr.readyState === XMLHttpRequest.DONE) {
- protyle.upload.isUploading = false;
- if (!document.body.contains(protyle.element)) {
- // 网络较慢时,页签已经关闭
- destroy(protyle);
+ formData.append("id", protyle.block.rootID);
+ confirmDialog(msg ? window.siyuan.languages.upload : "", msg, () => {
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", protyle.options.upload.url);
+ if (protyle.options.upload.token) {
+ xhr.setRequestHeader("X-Upload-Token", protyle.options.upload.token);
+ }
+ if (protyle.options.upload.withCredentials) {
+ xhr.withCredentials = true;
+ }
+
+ protyle.upload.isUploading = true;
+ xhr.onreadystatechange = () => {
+ if (xhr.readyState === XMLHttpRequest.DONE) {
+ protyle.upload.isUploading = false;
+ if (!document.body.contains(protyle.element)) {
+ // 网络较慢时,页签已经关闭
+ destroy(protyle);
+ return;
+ }
+ if (xhr.status === 200) {
+ hideMessage(validateResult.msgId);
+ if (protyle.options.upload.success) {
+ protyle.options.upload.success(editorElement, xhr.responseText);
+ } else if (successCB) {
+ successCB(xhr.responseText);
+ } else {
+ let responseText = xhr.responseText;
+ if (protyle.options.upload.format) {
+ responseText = protyle.options.upload.format(files as File [], xhr.responseText);
+ }
+ genUploadedLabel(responseText, protyle);
+ }
+ } else if (xhr.status === 0) {
+ showMessage(window.siyuan.languages.fileTypeError);
+ } else {
+ if (protyle.options.upload.error) {
+ protyle.options.upload.error(xhr.responseText);
+ } else {
+ showMessage(xhr.responseText);
+ }
+ }
+ if (element) {
+ element.value = "";
+ }
+ protyle.upload.element.style.display = "none";
+ }
+ };
+ xhr.upload.onprogress = (event: ProgressEvent) => {
+ if (!event.lengthComputable) {
return;
}
- if (xhr.status === 200) {
- hideMessage(validateResult.msgId);
- if (protyle.options.upload.success) {
- protyle.options.upload.success(editorElement, xhr.responseText);
- } else if (successCB) {
- successCB(xhr.responseText);
- } else {
- let responseText = xhr.responseText;
- if (protyle.options.upload.format) {
- responseText = protyle.options.upload.format(files as File [], xhr.responseText);
- }
- genUploadedLabel(responseText, protyle);
- }
- } else if (xhr.status === 0) {
- showMessage(window.siyuan.languages.fileTypeError);
- } else {
- if (protyle.options.upload.error) {
- protyle.options.upload.error(xhr.responseText);
- } else {
- showMessage(xhr.responseText);
- }
- }
- if (element) {
- element.value = "";
- }
- protyle.upload.element.style.display = "none";
- }
- };
- xhr.upload.onprogress = (event: ProgressEvent) => {
- if (!event.lengthComputable) {
- return;
- }
- const progress = event.loaded / event.total * 100;
- protyle.upload.element.style.display = "block";
- const progressBar = protyle.upload.element;
- progressBar.style.width = progress + "%";
- };
- xhr.send(formData);
+ const progress = event.loaded / event.total * 100;
+ protyle.upload.element.style.display = "block";
+ const progressBar = protyle.upload.element;
+ progressBar.style.width = progress + "%";
+ };
+ xhr.send(formData);
+ });
};
diff --git a/app/src/protyle/util/compatibility.ts b/app/src/protyle/util/compatibility.ts
index 16d25c6e9..71dfc16ee 100644
--- a/app/src/protyle/util/compatibility.ts
+++ b/app/src/protyle/util/compatibility.ts
@@ -122,13 +122,13 @@ export const readText = () => {
/// #if !BROWSER
export const getLocalFiles = async () => {
// 不再支持 PC 浏览器 https://github.com/siyuan-note/siyuan/issues/7206
- let localFiles: string[] = [];
+ let localFiles: ILocalFiles[] = [];
if ("darwin" === window.siyuan.config.system.os) {
const xmlString = clipboard.read("NSFilenamesPboardType");
const domParser = new DOMParser();
const xmlDom = domParser.parseFromString(xmlString, "application/xml");
Array.from(xmlDom.getElementsByTagName("string")).forEach(item => {
- localFiles.push(item.childNodes[0].nodeValue);
+ localFiles.push({path: item.childNodes[0].nodeValue, size: null});
});
} else {
const xmlString = await fetchSyncPost("/api/clipboard/readFilePaths", {});
diff --git a/app/src/protyle/util/editorCommonEvent.ts b/app/src/protyle/util/editorCommonEvent.ts
index 1ccc01a61..bf58344cc 100644
--- a/app/src/protyle/util/editorCommonEvent.ts
+++ b/app/src/protyle/util/editorCommonEvent.ts
@@ -1149,9 +1149,12 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
if (!avElement) {
focusByRange(getRangeByPoint(event.clientX, event.clientY));
if (event.dataTransfer.types[0] === "Files" && !isBrowser()) {
- const files: string[] = [];
+ const files: ILocalFiles[] = [];
for (let i = 0; i < event.dataTransfer.files.length; i++) {
- files.push(webUtils.getPathForFile(event.dataTransfer.files[i]));
+ files.push({
+ path: webUtils.getPathForFile(event.dataTransfer.files[i]),
+ size: event.dataTransfer.files[i].size
+ });
}
uploadLocalFiles(files, protyle, !event.altKey);
} else {
@@ -1162,9 +1165,12 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
const cellElement = hasClosestByClassName(event.target, "av__cell");
if (cellElement) {
if (getTypeByCellElement(cellElement) === "mAsset" && event.dataTransfer.types[0] === "Files" && !isBrowser()) {
- const files: string[] = [];
+ const files: ILocalFiles[] = [];
for (let i = 0; i < event.dataTransfer.files.length; i++) {
- files.push(webUtils.getPathForFile(event.dataTransfer.files[i]));
+ files.push({
+ path: webUtils.getPathForFile(event.dataTransfer.files[i]),
+ size: event.dataTransfer.files[i].size
+ });
}
dragUpload(files, protyle, cellElement);
clearSelect(["cell"], avElement);
diff --git a/app/src/protyle/util/paste.ts b/app/src/protyle/util/paste.ts
index cb59b8a33..b22a11a8a 100644
--- a/app/src/protyle/util/paste.ts
+++ b/app/src/protyle/util/paste.ts
@@ -148,7 +148,7 @@ export const pasteEscaped = async (protyle: IProtyle, nodeElement: Element) => {
};
export const pasteAsPlainText = async (protyle: IProtyle) => {
- let localFiles: string[] = [];
+ let localFiles: ILocalFiles[] = [];
/// #if !BROWSER
localFiles = await getLocalFiles();
if (localFiles.length > 0) {
@@ -214,24 +214,24 @@ export const restoreLuteMarkdownSyntax = (protyle: IProtyle) => {
protyle.lute.SetMark(window.siyuan.config.editor.markdown.inlineMark);
};
-const readLocalFile = async (protyle: IProtyle, localFiles: string[]) => {
+const readLocalFile = async (protyle: IProtyle, localFiles: ILocalFiles[]) => {
if (protyle && protyle.app && protyle.app.plugins) {
for (let i = 0; i < protyle.app.plugins.length; i++) {
- const response: { files: string[] } = await new Promise((resolve) => {
+ const response: { localFiles: ILocalFiles[] } = await new Promise((resolve) => {
const emitResult = protyle.app.plugins[i].eventBus.emit("paste", {
protyle,
resolve,
textHTML: "",
textPlain: "",
siyuanHTML: "",
- files: localFiles
+ localFiles
});
if (emitResult) {
resolve(undefined);
}
});
- if (response?.files) {
- localFiles = response.files;
+ if (response?.localFiles) {
+ localFiles = response.localFiles;
}
}
}
@@ -277,7 +277,7 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
/// #if !BROWSER
if (!siyuanHTML && !textHTML && !textPlain && ("clipboardData" in event)) {
- const localFiles: string[] = await getLocalFiles();
+ const localFiles: ILocalFiles[] = await getLocalFiles();
if (localFiles.length > 0) {
readLocalFile(protyle, localFiles);
return;
diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts
index 19b4af116..f7f9045f0 100644
--- a/app/src/types/index.d.ts
+++ b/app/src/types/index.d.ts
@@ -286,12 +286,17 @@ interface Window {
destroyTheme(): Promise;
}
+interface ILocalFiles {
+ path: string,
+ size: number
+}
+
interface IClipboardData {
textHTML?: string,
textPlain?: string,
siyuanHTML?: string,
files?: File[],
- localFiles?: string[]
+ localFiles?: ILocalFiles[],
}
interface IRefDefs {