-
-
Notifications
You must be signed in to change notification settings - Fork 363
feat(Upload): use local preview instead of base64 format #6157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
308e728
1d92a3d
64e52eb
2c9c2be
186b9bf
1b6a9fd
d8b8453
74053c0
4ade24e
5f86566
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -133,6 +133,21 @@ protected override void OnParametersSet() | |
| RemoveIcon ??= IconTheme.GetIconByKey(ComponentIcons.CardUploadRemoveIcon); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// <inheritdoc/> | ||
| /// </summary> | ||
| /// <param name="file"></param> | ||
| /// <returns></returns> | ||
| protected override async Task TriggerOnChanged(UploadFile file) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Image preview logic duplicated here as well Consider refactoring this logic into a shared base class or utility method to avoid duplication. |
||
| { | ||
| // 从客户端获得预览地址不使用 base64 编码 | ||
| if (file.IsImage(AllowExtensions, CanPreviewCallback)) | ||
| { | ||
| file.PrevUrl = await InvokeAsync<string?>("getPreviewUrl", Id, file.OriginFileName); | ||
| } | ||
| await base.TriggerOnChanged(file); | ||
| } | ||
|
|
||
| private async Task OnCardFileDelete(UploadFile item) | ||
| { | ||
| await OnFileDelete(item); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,24 @@ | ||
| import Data from "./data.js" | ||
| import EventHandler from "./event-handler.js" | ||
| import { readFileAsync } from "./utility.js" | ||
|
|
||
| export function init(id) { | ||
| const el = document.getElementById(id) | ||
| if (el === null) { | ||
| return | ||
| } | ||
| const preventHandler = e => e.preventDefault() | ||
| const preventHandler = e => e.preventDefault(); | ||
| const body = el.querySelector('.upload-drop-body'); | ||
| const upload = { el, body, preventHandler } | ||
| const inputFile = el.querySelector('[type="file"]'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): inputFile can be null; add a null-check before usage Add a guard or early return to handle cases where inputFile is null to avoid runtime errors. |
||
| const upload = { el, body, preventHandler, inputFile }; | ||
| Data.set(id, upload) | ||
|
|
||
| const inputFile = el.querySelector('[type="file"]') | ||
| EventHandler.on(el, 'click', '.btn-browser', () => { | ||
| inputFile.click() | ||
| }) | ||
| EventHandler.on(inputFile, 'change', e => { | ||
| upload.files = e.delegateTarget.files; | ||
| }); | ||
|
|
||
| EventHandler.on(document, "dragleave", preventHandler) | ||
| EventHandler.on(document, 'drop', preventHandler) | ||
|
|
@@ -79,12 +83,28 @@ export function init(id) { | |
| }) | ||
| } | ||
|
|
||
| export async function getPreviewUrl(id, fileName) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): Consider refactoring getPreviewUrl to use early returns and optional chaining to reduce nesting and intermediate variables. Here’s a way to flatten out the nesting in export async function getPreviewUrl(id, fileName) {
const files = Data.get(id)?.files;
if (!files) return '';
// find the File object
const file = Array.from(files).find(f => f.name === fileName);
if (!file) return '';
// readFileAsync → blob URL
const blob = await readFileAsync(file);
return blob ? URL.createObjectURL(blob) : '';
}If you’re not actually transforming the file (just wrapping it in a blob URL), you can simplify further and drop export function getPreviewUrl(id, fileName) {
const files = Data.get(id)?.files || [];
const file = files.find(f => f.name === fileName);
return file ? URL.createObjectURL(file) : '';
}Both versions preserve the current behavior while reducing indentation, intermediate variables, and nested |
||
| let url = ''; | ||
| const upload = Data.get(id); | ||
| const { files } = upload; | ||
| if (files) { | ||
| const file = [...files].find(v => v.name === fileName); | ||
| if (file) { | ||
| const data = await readFileAsync(file); | ||
| if (data) { | ||
| url = URL.createObjectURL(data); | ||
| } | ||
| } | ||
| } | ||
| return url; | ||
| } | ||
|
|
||
| export function dispose(id) { | ||
| const upload = Data.get(id) | ||
| Data.remove(id) | ||
|
|
||
| if (upload) { | ||
| const { el, body, preventHandler } = upload; | ||
| const { el, body, preventHandler, inputFile } = upload; | ||
|
|
||
| EventHandler.off(document, 'dragleave', preventHandler) | ||
| EventHandler.off(document, 'drop', preventHandler) | ||
|
|
@@ -94,6 +114,7 @@ export function dispose(id) { | |
| EventHandler.off(el, 'click') | ||
| EventHandler.off(el, 'drop') | ||
| EventHandler.off(el, 'paste') | ||
| EventHandler.off(inputFile, 'change') | ||
| EventHandler.off(body, 'dragleave') | ||
| EventHandler.off(body, 'drop') | ||
| EventHandler.off(body, 'dragenter') | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -886,6 +886,27 @@ export function drawImage(canvas, image, offsetWidth, offsetHeight) { | |||||||||||||||||||||||||||||||
| context.drawImage(image, 0, 0, offsetWidth, offsetHeight); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||
| * @param {File} file | ||||||||||||||||||||||||||||||||
| * @returns {Blob} | ||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| export function readFileAsync(file) { | ||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): Consider removing or simplifying the readFileAsync helper to avoid unnecessary FileReader logic.
Suggested change
Or (clone via slice): /** @param {File} file
* @returns {Promise<Blob>}
*/
export function readFileAsync(file) {
const blobCopy = file.slice(0, file.size, file.type);
return Promise.resolve(blobCopy);
}Both eliminate the 20+ lines of |
||||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||||
| const reader = new FileReader(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| reader.onload = () => { | ||||||||||||||||||||||||||||||||
| const blob = new Blob([reader.result], { type: file.type }); | ||||||||||||||||||||||||||||||||
| resolve(blob); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| reader.onerror = (error) => { | ||||||||||||||||||||||||||||||||
| reject(error); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| reader.readAsArrayBuffer(file); | ||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| export { | ||||||||||||||||||||||||||||||||
| autoAdd, | ||||||||||||||||||||||||||||||||
| autoRemove, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): Non-image files retain previous PrevUrl
Reset PrevUrl for non-image files to prevent showing outdated previews.