mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-02-23 05:31:06 +01:00
Et2File: Improvements for handling larger files
This commit is contained in:
parent
8beae0adee
commit
fce8540da5
@ -4,6 +4,9 @@ export default css`
|
|||||||
:host {
|
:host {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:host([loading]) .file__button et2-image {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.file--single > div {
|
.file--single > div {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -98,6 +98,8 @@ export class Et2File extends Et2InputWidget(LitElement)
|
|||||||
|
|
||||||
@property({type: Object}) uploadOptions : {};
|
@property({type: Object}) uploadOptions : {};
|
||||||
|
|
||||||
|
/** Chunk size can be altered by the server */
|
||||||
|
@property({type: Number}) chunkSize = 1020 * 1024;
|
||||||
|
|
||||||
@property({type: Function}) onStart : Function;
|
@property({type: Function}) onStart : Function;
|
||||||
@property({type: Function}) onFinishOne : Function;
|
@property({type: Function}) onFinishOne : Function;
|
||||||
@ -106,7 +108,7 @@ export class Et2File extends Et2InputWidget(LitElement)
|
|||||||
@state() files : FileInfo[] = [];
|
@state() files : FileInfo[] = [];
|
||||||
|
|
||||||
protected resumable : Resumable = null;
|
protected resumable : Resumable = null;
|
||||||
private __value : { [tempName : string] : FileInfo };
|
private __value : { [tempName : string] : FileInfo } = {};
|
||||||
|
|
||||||
/** Files already uploaded */
|
/** Files already uploaded */
|
||||||
@property({type: Object})
|
@property({type: Object})
|
||||||
@ -197,11 +199,14 @@ export class Et2File extends Et2InputWidget(LitElement)
|
|||||||
request_id: this.getInstanceManager()?.etemplate_exec_id,
|
request_id: this.getInstanceManager()?.etemplate_exec_id,
|
||||||
widget_id: this.id,
|
widget_id: this.id,
|
||||||
},
|
},
|
||||||
chunkSize: 1024 * 1024,
|
chunkSize: this.chunkSize,
|
||||||
|
|
||||||
// Checking for already uploaded chunks - resumable uploads
|
// Checking for already uploaded chunks - resumable uploads
|
||||||
testChunks: true,
|
testChunks: true,
|
||||||
testTarget: this.egw().ajaxUrl("EGroupware\\Api\\Etemplate\\Widget\\File::ajax_test_chunk")
|
testTarget: this.egw().ajaxUrl("EGroupware\\Api\\Etemplate\\Widget\\File::ajax_test_chunk"),
|
||||||
|
|
||||||
|
// Failure & retry
|
||||||
|
//xhrTimeout: 10000
|
||||||
};
|
};
|
||||||
if(this.accept)
|
if(this.accept)
|
||||||
{
|
{
|
||||||
@ -279,6 +284,11 @@ export class Et2File extends Et2InputWidget(LitElement)
|
|||||||
if(fileItem && file.progress())
|
if(fileItem && file.progress())
|
||||||
{
|
{
|
||||||
fileItem.progress = file.progress() * 100;
|
fileItem.progress = file.progress() * 100;
|
||||||
|
// Show indeterminate while processing
|
||||||
|
if(fileItem.progress == 100)
|
||||||
|
{
|
||||||
|
delete fileItem.progress;
|
||||||
|
}
|
||||||
fileItem.requestUpdate("progress");
|
fileItem.requestUpdate("progress");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,14 +499,27 @@ export class Et2File extends Et2InputWidget(LitElement)
|
|||||||
|
|
||||||
handleFileRemove(info : FileInfo)
|
handleFileRemove(info : FileInfo)
|
||||||
{
|
{
|
||||||
const index = this.files.indexOf(info);
|
let index = this.files.indexOf(info);
|
||||||
|
if(index === -1)
|
||||||
|
{
|
||||||
|
const source = <FileInfo[]>Object.values(this.value);
|
||||||
|
index = source.indexOf(info);
|
||||||
|
delete this.value[Object.keys(this.value)[index]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.files.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if(index === -1)
|
if(index === -1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileInfo = this.files[index];
|
if(info && typeof info.progress == "function" && typeof info.abort == "function" && info.progress() < 1)
|
||||||
|
{
|
||||||
|
info.abort();
|
||||||
|
}
|
||||||
|
|
||||||
this.files.splice(index, 1);
|
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
|
|
||||||
this.updateComplete.then(() =>
|
this.updateComplete.then(() =>
|
||||||
@ -528,21 +551,24 @@ export class Et2File extends Et2InputWidget(LitElement)
|
|||||||
|
|
||||||
fileItemTemplate(fileInfo : FileInfo, index)
|
fileItemTemplate(fileInfo : FileInfo, index)
|
||||||
{
|
{
|
||||||
|
const label = (fileInfo.accepted ? fileInfo.file.name : fileInfo.warning) ?? fileInfo['name'];
|
||||||
let icon = fileInfo.icon ?? (fileInfo.warning ? "exclamation-triangle" : undefined);
|
let icon = fileInfo.icon ?? (fileInfo.warning ? "exclamation-triangle" : undefined);
|
||||||
|
|
||||||
// Pull thumbnail from file if we can
|
// Pull thumbnail from file if we can
|
||||||
|
const type = fileInfo.file?.type ?? fileInfo["type"];
|
||||||
let thumbnail;
|
let thumbnail;
|
||||||
if(!icon && fileInfo.file && fileInfo.file.type?.startsWith("image/"))
|
if(!icon && fileInfo.file && type?.startsWith("image/"))
|
||||||
{
|
{
|
||||||
thumbnail = URL.createObjectURL(fileInfo.file);
|
thumbnail = URL.createObjectURL(fileInfo.file);
|
||||||
}
|
}
|
||||||
|
const closable = !this.readonly && (fileInfo.accepted || Object.values(this.value).indexOf(fileInfo) !== -1)
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<et2-file-item
|
<et2-file-item
|
||||||
display=${this.display}
|
display=${this.display}
|
||||||
size=${fileInfo.accepted ? fileInfo.file.size : nothing}
|
size=${fileInfo.accepted ? fileInfo.file.size : nothing}
|
||||||
variant=${fileInfo.accepted && !fileInfo.warning ? "default" : "warning"}
|
variant=${fileInfo.accepted && !fileInfo.warning ? "default" : "warning"}
|
||||||
?closable=${fileInfo.accepted}
|
?closable=${closable}
|
||||||
?loading=${fileInfo.loading}
|
?loading=${fileInfo.loading}
|
||||||
image=${ifDefined(icon)}
|
image=${ifDefined(icon)}
|
||||||
progress=${typeof fileInfo.progress == "function" ? fileInfo.progress() : (fileInfo.progress ?? nothing)}
|
progress=${typeof fileInfo.progress == "function" ? fileInfo.progress() : (fileInfo.progress ?? nothing)}
|
||||||
@ -560,19 +586,19 @@ export class Et2File extends Et2InputWidget(LitElement)
|
|||||||
this.handleFileRemove(fileInfo);
|
this.handleFileRemove(fileInfo);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
${!icon && thumbnail || !fileInfo.file.type ? html`
|
${!icon && thumbnail || !type ? html`
|
||||||
<et2-image slot="image"
|
<et2-image slot="image"
|
||||||
src=${thumbnail ?? "upload"}
|
src=${thumbnail ?? "upload"}
|
||||||
/>
|
/>
|
||||||
` : nothing}
|
` : nothing}
|
||||||
${!icon && !thumbnail && fileInfo.file.type ? html`
|
${!icon && !thumbnail && type ? html`
|
||||||
<et2-vfs-mime
|
<et2-vfs-mime
|
||||||
slot="image"
|
slot="image"
|
||||||
mime=${fileInfo.file.type}
|
mime=${type}
|
||||||
.value=${{mime: fileInfo.file.type}}
|
.value=${{mime: type}}
|
||||||
></et2-vfs-mime>` : nothing
|
></et2-vfs-mime>` : nothing
|
||||||
}
|
}
|
||||||
${fileInfo.accepted ? fileInfo.file.name : fileInfo.warning}
|
${label}
|
||||||
</et2-file-item>
|
</et2-file-item>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -296,9 +296,15 @@ class File extends Etemplate\Widget
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the final destination file
|
// create the final destination file
|
||||||
|
set_time_limit($total_files / 100);
|
||||||
if (($fp = fopen($new_file, 'w')) !== false) {
|
if (($fp = fopen($new_file, 'w')) !== false) {
|
||||||
for ($i=1; $i<=$total_files; $i++) {
|
for ($i=1; $i<=$total_files; $i++) {
|
||||||
fwrite($fp, file_get_contents($temp_dir.'/'.$fileName.'.part'.$i));
|
$chunk = fopen($temp_dir . '/' . $fileName . '.part' . $i, 'r');
|
||||||
|
while(!feof($chunk))
|
||||||
|
{
|
||||||
|
fwrite($fp, fread($chunk, 1024 * 1024));
|
||||||
|
}
|
||||||
|
fclose($chunk);
|
||||||
}
|
}
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
} else {
|
} else {
|
||||||
@ -413,9 +419,21 @@ class File extends Etemplate\Widget
|
|||||||
$unit = strtolower(substr($upload_max_filesize, -1));
|
$unit = strtolower(substr($upload_max_filesize, -1));
|
||||||
$upload_max_filesize = (float)$upload_max_filesize;
|
$upload_max_filesize = (float)$upload_max_filesize;
|
||||||
if (!is_numeric($unit)) $upload_max_filesize *= $unit === 'm' ? 1024*1024 : 1024;
|
if (!is_numeric($unit)) $upload_max_filesize *= $unit === 'm' ? 1024*1024 : 1024;
|
||||||
if ($upload_max_filesize > 1024*1024)
|
|
||||||
|
$current_max_chunk = self::getElementAttribute($form_name, 'chunkSize') ?? $this->attrs['chunkSize'];
|
||||||
|
if($current_max_chunk)
|
||||||
{
|
{
|
||||||
self::setElementAttribute($form_name, 'chunk_size', ($upload_max_filesize-1024*1024)/2);
|
$unit = strtolower(substr($current_max_chunk, -1));
|
||||||
|
$current_max_chunk = (float)$current_max_chunk;
|
||||||
|
if(!is_numeric($unit))
|
||||||
|
{
|
||||||
|
$current_max_chunk *= $unit === 'm' ? 1024 * 1024 : 1024;
|
||||||
|
}
|
||||||
|
$upload_max_filesize = min($upload_max_filesize, $current_max_chunk);
|
||||||
|
}
|
||||||
|
if($upload_max_filesize != 1024 * 1024)
|
||||||
|
{
|
||||||
|
self::setElementAttribute($form_name, 'chunkSize', ($upload_max_filesize - 1024 * 1024) / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -485,12 +485,19 @@ export class filemanagerAPP extends EgwApp
|
|||||||
if(_file_count && _event.detail)
|
if(_file_count && _event.detail)
|
||||||
{
|
{
|
||||||
let widget = _event.target;
|
let widget = _event.target;
|
||||||
|
widget.loading = true;
|
||||||
|
_event.detail.accepted = false; // Turn off removable, it's too late now
|
||||||
let value = widget.getValue();
|
let value = widget.getValue();
|
||||||
value.conflict = _conflict;
|
value.conflict = _conflict;
|
||||||
|
widget.requestUpdate("loading");
|
||||||
egw.json(_target, ['upload', value, _path, {ui_path: this.egw.window.location.pathname}],
|
egw.json(_target, ['upload', value, _path, {ui_path: this.egw.window.location.pathname}],
|
||||||
this._upload_callback, this, true, this
|
this._upload_callback, this, true, this
|
||||||
).sendRequest();
|
).sendRequest().finally(() =>
|
||||||
widget.value = {};
|
{
|
||||||
|
widget.loading = false;
|
||||||
|
widget.value = {};
|
||||||
|
widget.requestUpdate("loading", true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user