kukhariev / ngx-uploadx Goto Github PK
View Code? Open in Web Editor NEWAngular Resumable Upload Module
Home Page: https://github.com/kukhariev/ngx-uploadx
License: MIT License
Angular Resumable Upload Module
Home Page: https://github.com/kukhariev/ngx-uploadx
License: MIT License
Describe the bug
When prerendering an angular app server side with UploadxModule imported in the ngModule I obtain a window is not defined
error. I already tried to polyfill the window obj as suggested for example here: angular/universal#1523
But with no success with ngx-uploadx (I made all other dependencies of my project to work on ssr but failed with ngx-uploadx)
To Reproduce
I basically followed the setup explained here: https://github.com/angular-university/angular-universal-course/tree/master
then when executing the prerendering I obtain the error window is not defined
that made the prerendering to fail
Expected behavior
ngx-uploadx should work when the page is prerendered server side or at least silently fail. I'm pretty new to angular ssr so I don't know exactly how ngx-uploadx should behave
Setup details:
ngx-uploadx
4.0.1Describe the bug
The pause with uploadId seems to be pausing all the queue.
To Reproduce
calling simply the service passing the uploadId.
this.uploadService.control({ action: 'pause', uploadId });
Expected behavior
Only the element with the uploadId should be paused.
Setup details:
ngx-uploadx
latestHi,
When i try to upload a file with a size of 0 the upload is being retried endlessly after recieving a successfull response ( 201 )
Request headers
PUT
Content-Length: 0
Content-Range: bytes 0--1/0
Response headers
HTTP/1.1 201 Created
Range: 0--1
probably this is a silly question and not the place to put it, but is there any consistent way to rename the file once is in the queue already?
i'm using NGXS to handle the uploads with an application store and i'm copying the content of the uploadService queue into my own thing, however my rename functionality gets overwritten by what it is inside the queue at the time i restart the upload.
the endpoint gets updated properly and the file sent to the server have the proper name, but visually my user will still see the old name.
hope this makes sense since this is not a bug.
i can't copy my code since is a corporate application.
but the state is just a copy of the queue.
i'm using the latest of the library.
Apologies if the following isn't 100% clear. I can clarify further. But in a nutshell the main question is: why does the code change the endpoint from https://...
to http://...
when the origin is http
and is that a bug?
---- Thanks very much for a great piece of software regardless!
In this entire discussion, I am using UploadxService.handleFile()
- that's where the URL of the endpoint specified in the options object given to it gets automatically converted from https
to http
(only when running from an http
origin).
When developing / testing the code, I serve my single page app on a local machine server and go to url http://localhost:8100
to test a running of the app.
That app connects to an Uploadx node server that sits behind https
protocol, and runs on a URL like:
https://upload.example.com
When the app is served from an https
origin, e.g. https://app.example.com
- then everything works as expected - the app can access the Uploadx node server with no problem, all works.
But when I develop / test the code and serve the app locally, the origin has protocol http
, not https
. In that case, for some reason, when using handleFile
of the service version of Uploadx (UploadxService
), it changes the protocol when making the request, even though the endpoint I specify in options given to handle file is preceded by https
. I give handle file()
the option endopoint: https://upload.example.com/upload
but it actually changes that endpoint and makes the request at a different URL, changing the protocol from https
to http
, i.e. it goes to endpoint http://upload.example.com/upload
instead, because the origin had http
in it.
This causes a problem, I need to access the https:
endpoint always, not the http
but it gets converted automatically in the code. Is there a way to stop it from converting from https
to http
when the origin is http
?
Update
I am noticing in the logs of the server side (Uploadx node server) that the endpoint actually seems to have the protocol stripped when it arrives - here's a line from the Uploadx server log:
<ip#> - - [20/Sep/2019:21:49:15 +0000] "OPTIONS /upload?uploadType=uploadx&upload_id=52014dbf3fbda4e3cef2f4ec3c0f2c53 ...
So it's not that https
gets converted to http
but it gets stripped, then http
is assumed because of the origin's http
that it comes from. It's possible I am not understanding something here, but perhaps if we kept the https://
and did not strip it from the endpoint URL, that would solve the problem?
More specifically, looking at the Network tab of the developer tools in chrome when running the app from origin http://localhost:8100
, and uploading one file via handleFile, I see the following sequence of requests (using example.com
instead of my actual server):
https://upload.example.com/upload?uploadType=uploadx (status 204)
https://upload.example.com/upload?uploadType=uploadx (status 201)
http://upload.example.com/upload?uploadType=uploadx&upload_id=... (status 301)
http://upload.example.com/upload?uploadType=uploadx&upload_id=... (status 301)
http://upload.example.com/upload?uploadType=uploadx&upload_id=... (status 301)
http://upload.example.com/upload?uploadType=uploadx&upload_id=... (status 301)
http://upload.example.com/upload?uploadType=uploadx&upload_id=... (status 301)
...
i.e. as soon as we see an &upload_id in the URL, it becomes http
while it should be https
to work for my use case.
How to replicate
https
http://localhost*
that uploads a file to the server above via UploadxServer.handleFile()
- the upload will fail as described above.You can't select a file again, which upload is canceled.
Follow Tasks to reproduce:
If an upload is cancelled, it's not removed from upload queue in service
Is your feature request related to a problem? Please describe.
Uploading files bigger than 5 gb directly to S3 buckets using ngx-uploadx
Describe the solution you'd like
On projects with S3 Storage, you can create a presigned url in order to let the angular client upload their files directly to S3. This saves a lot of time and ressources, since the webserver itself does nothing but creating this presigned url.
(Details: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html#query-string-auth-v4-signing-example)
I would like to use Multipartuploads with ngx-uploadx in that scenario https://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html
Describe alternatives you've considered
no alternatives yet
Additional context
options setting
options: UploadxOptions = { endpoint: API_URL, token: () => this.authService.token, chunkSize: 1024 * 1024 * 1, autoUpload: false };
I want to send a request header with:
But right now request header with:
Version
ngx-uploadx 3.3.4
Angular 8.2.14
Refference: https://github.com/senolatac/chunk-upload/tree/develop
Hi,
Do ngx-uploadx allow upload to different endpoint in the same component? For example:
I have 2 input tags:
<input
#files
(click)="files.value = ''"
type="file"
[uploadx]="options" // <--- upload to enpoint 1
[uploadxAction]="control"
(uploadxState)="onUpload($event)"
multiple
style="display:none"
/>
<input
#files
(click)="files.value = ''"
type="file"
[uploadx]="options" // <--- upload to enpoint 2
[uploadxAction]="control"
(uploadxState)="onUpload($event)"
multiple
style="display:none"
/>
Thanks
Describe the bug
If an upload item in the queue is cancel with the "control" method, the "events" observable is not called.
To Reproduce
Expected behavior
Events should be called on each state change.
Setup details:
ngx-uploadx
3.3.3I'm using the library in a system where the files can be uploaded to more than one endpoint, and is a little bit difficult to change the endpoint for different files, because is not nice to change the service configuration each time i need to upload a file (that what i'm doing now):
autoUpload
as falseoptions: UploadxOptions = {
concurrency: 2,
autoUpload: false,
chunkSize: 1024 * 256 * 8
};
this.uploadxService.handleFile(file); // Put the file ready to upload
let itemId = null;
return this.uploadsProgress.pipe(
map((item: UploadState) => {
if (!itemId && item.status === 'added') {
itemId = item.uploadId;
this.uploadxService.control({
action: 'upload',
itemOptions: {
token: 'toekneeeeeeeeeee',
uploadId: itemId,
endpoint: apiEndpoint,
method: 'POST'
} as UploadItem
} as UploadxControlEvent);
}
return item;
}),
filter((item: UploadState) => item.status === 'cancelled' || item.status === 'complete' || item.status === 'error' && item.uploadId === itemId)
);
this should work but the endpoint is not updated in the configure method in Uploader class:
configure(item = {} as UploadItem): void {
const { metadata, headers, token } = item;
this.metadata = {
name: this.name,
mimeType: this.mimeType,
size: this.size,
...unfunc(metadata || this.metadata, this.file)
};
this.chunkSize = this.options.chunkSize || this.chunkSize;
this.maxRetryAttempts = this.options.maxRetryAttempts || this.maxRetryAttempts;
this.refreshToken(token);
this.headers = { ...this.headers, ...unfunc(headers, this.file) };
}
Other idea is to return the uploader in the handler
method because right now i need to take the uploaderId
in the uploadsProgress as an even of the service.
As far as I know about tus, the client should check if the same file has been uploaded before. if so the upload progress should be fasten and reach 100% in one second.
Here is my observation while running up this demo by "npm start" and uploading the same file several times:
Thanks
ngx-uploadx/src/uploadx/lib/uploader.ts
Lines 134 to 137 in bc7a900
TODO
comment in bc7a900 when #241 was merged. cc @kukhariev.Hi,
I have cloned this repository and run it up with "npm install", drag and drop a file, it could be uploaded successfully. But in middle of uploading if I refresh the web page (mimic that the laptop is shutdown or browser is closed unexpectedly), re-uploading the same file seems transferring from the head because the progress is starting from 0%. No matter I tried "tus", "service" or "directive" mode in this demo, the same result. What I had thought re-uploading the same file should go from the progress where it is interrupted, is anything misunderstanding?
Thanks
Hi !
After tests in my app, IE doesn't seems to work with this component.
I modified the 'uploader.ts' file by inverting 'xhr.open(..' lines with 'xhr.responseType = 'json'' lines
import { BackoffRetry } from './backoffRetry';
import { XHRFactory } from './xhrfactory';
import {
UploadStatus,
UploadItem,
UploaderOptions,
UploadState
} from './interfaces';
const noop = () => {};
/**
* Implements XHR/CORS Resumable Upload
* @see
* https://developers.google.com/drive/v3/web/resumable-upload
*/
export class Uploader implements UploaderOptions {
headers: any;
metadata: any;
method: string;
mimeType: string;
name: string;
progress: number;
remaining: number;
response: any;
size: number;
speed: number;
uploadId: string;
url: any;
private startTime: number;
private _status: UploadStatus;
private retry: BackoffRetry;
private abort;
/**
* Creates an instance of Uploader.
*/
constructor(private file: File, private options: UploaderOptions) {
this.uploadId = Math.random()
.toString(36)
.substring(2, 15);
this.name = file.name;
this.size = file.size;
this.mimeType = file.type || 'application/octet-stream';
this.status = 'added';
this.retry = new BackoffRetry();
}
/**
* Set individual file options and add to queue
*/
configure(item: UploadItem = {}) {
if (this.status === 'added') {
const { metadata, headers } = item;
this.metadata = {
name: this.name,
mimeType: this.mimeType,
...this.options.metadata,
...metadata
};
this.headers =
this.options.headers instanceof Function
? this.options.headers(this.file)
: { ...this.options.headers, ...headers };
this.url = this.options.url;
this.method = this.options.method;
}
this.status = 'queue';
}
set status(s: UploadStatus) {
this._status = s;
this.notifyState();
if (s === 'cancelled' || s === 'paused') {
this.abort();
}
}
get status() {
return this._status;
}
/**
* Emit current state
*/
private notifyState() {
const state: UploadState = {
file: this.file,
name: this.name,
progress: this.progress,
remaining: this.remaining,
response: this.response,
size: this.size,
speed: this.speed,
status: this._status,
uploadId: this.uploadId,
URI: this.url
};
// tick for control events detect
setTimeout(() => {
this.options.subj.next(state);
});
}
private setHeaders(xhr: XMLHttpRequest) {
if (this.headers) {
Object.keys(this.headers).forEach(key =>
xhr.setRequestHeader(key, this.headers[key])
);
}
}
/**
* Initiate upload
*/
upload() {
if (this.status === 'added') {
this.configure();
}
this.status = 'uploading';
if (this.progress > 0) {
return this.resume();
}
const xhr = new XMLHttpRequest();
xhr.open(this.method, this.options.url, true);
xhr.responseType = 'json';
if (!!this.options.withCredentials) {
xhr.withCredentials = true;
}
this.setHeaders(xhr);
this.options.token
? xhr.setRequestHeader('Authorization', 'Bearer ' + this.options.token)
: noop();
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.setRequestHeader('X-Upload-Content-Length', this.size.toString());
xhr.setRequestHeader('X-Upload-Content-Type', this.mimeType);
xhr.onload = () => {
if (xhr.status < 400 && xhr.status > 199) {
// get secure upload link
this.url = xhr.getResponseHeader('Location');
this.startTime = this.startTime || new Date().getTime();
this.sendFile();
} else {
this.response = xhr.response;
this.status = 'error';
}
};
xhr.send(JSON.stringify(this.metadata));
}
/**
* Request upload state after 5xx errors or network failures
*/
private resume(): void {
const xhr: XMLHttpRequest = XHRFactory.getInstance();
xhr.open('PUT', this.url, true);
if (xhr.responseType !== 'json') {
xhr.responseType = 'json';
}
if (!!this.options.withCredentials) {
xhr.withCredentials = true;
}
xhr.setRequestHeader('Content-Range', `bytes */${this.size}`);
xhr.setRequestHeader('Content-Type', this.mimeType);
this.setHeaders(xhr);
const onDataSendError = () => {
// 5xx errors or network failures
if (xhr.status > 499 || !xhr.status) {
XHRFactory.release(xhr);
this.retry.wait().then(() => this.resume());
} else {
// 4xx errors
this.response = xhr.response || {
error: {
code: xhr.status,
message: xhr.statusText
}
};
this.status = 'error';
XHRFactory.release(xhr);
this.options.nextFile();
}
};
const onDataSendSuccess = () => {
if (xhr.status === 200 || xhr.status === 201) {
this.progress = 100;
this.response = xhr.response;
this.status = 'complete';
XHRFactory.release(xhr);
this.options.nextFile();
} else if (xhr.status && xhr.status < 400) {
const range = +xhr.getResponseHeader('Range').split('-')[1] + 1;
this.retry.reset();
XHRFactory.release(xhr);
this.abort = this.sendFile(range);
} else {
onDataSendError();
}
};
xhr.onerror = onDataSendError;
xhr.onload = onDataSendSuccess;
xhr.send();
}
/**
* Content upload
*/
private sendFile(start: number = 0): () => void {
if (this.status === 'cancelled' || this.status === 'paused') {
return;
}
let end: number = this.options.chunkSize
? start + this.options.chunkSize
: this.size;
end = end > this.size ? this.size : end;
const chunk: Blob = this.file.slice(start, end);
const xhr: XMLHttpRequest = XHRFactory.getInstance();
xhr.open('PUT', this.url, true);
if (xhr.responseType !== 'json') {
xhr.responseType = 'json';
}
if (!!this.options.withCredentials) {
xhr.withCredentials = true;
}
xhr.setRequestHeader(
'Content-Range',
`bytes ${start}-${end - 1}/${this.size}`
);
xhr.setRequestHeader('Content-Type', this.mimeType);
this.setHeaders(xhr);
const updateProgress = (pEvent: ProgressEvent) => {
const uploaded = pEvent.lengthComputable
? start + (end - start) * (pEvent.loaded / pEvent.total)
: start;
this.progress = +(uploaded / this.size * 100).toFixed(2);
const now = new Date().getTime();
this.speed = Math.round(uploaded / (now - this.startTime) * 1000);
this.remaining = Math.ceil((this.size - uploaded) / this.speed);
this.notifyState();
};
const onDataSendError = () => {
// 5xx errors or network failures
if (xhr.status > 499 || !xhr.status) {
XHRFactory.release(xhr);
this.retry.wait().then(() => this.resume());
} else {
// 4xx errors
this.response = xhr.response || {
error: {
code: +xhr.status,
message: xhr.statusText
}
};
this.status = 'error';
XHRFactory.release(xhr);
this.options.nextFile();
}
};
const onDataSendSuccess = () => {
if (xhr.status === 200 || xhr.status === 201) {
this.progress = 100;
this.response = xhr.response;
this.status = 'complete';
XHRFactory.release(xhr);
this.options.nextFile();
} else if (xhr.status && xhr.status < 400) {
const range = +xhr.getResponseHeader('Range').split('-')[1] + 1;
this.retry.reset();
XHRFactory.release(xhr);
// send next chunk
this.abort = this.sendFile(range);
} else {
onDataSendError();
}
};
xhr.onerror = onDataSendError;
xhr.onload = onDataSendSuccess;
xhr.upload.onprogress = updateProgress;
xhr.send(chunk);
return () => {
xhr.abort();
};
}
}
If you use concurrency with chunks the next upload will be startet after the first chunk upload is complete.
Is your feature request related to a problem? Please describe.
An automated chunkSize
, under excellent network conditions, can lead to a chunk being larger than what the backend allows for security reasons and memory constraints.
Describe the solution you'd like
I would like a maxChunkSize
option, so that chunkSize
can be automatic but never exceed maxChunkSize
.
Describe alternatives you've considered
I have been using a fixed chunkSize
but that's not optimal.
Thanks for considering!
When the serve response came with an authentication error the library should handle this error (maybe create a new UploadStatus [error-auth]) for retry the upload when the token is refresh
Hi,
Hoping you could help me with the above issue in snip. Have been able to send initial request to my net core api but on return to angular client, the error in image above is thrown. Have tried adding a "Location" and "Content-Location" header but with no luck. Currently, because of error, request is retried which makes sense. Have you any documentation or information on what this error relates to and what kind of response is expected back from my backend.
Also, was wondering if there is a way for my angular client to pass the chunk index to my backend. ie file has 4 chunks so with each chunk, pass param or header value with chunk index 1 - 4. Apologies for raising this as issue. This is a support query and I couldn't find any decent threads on stackoverflow.
Hello,
I'm sorry but refreshToken control don't work as it was.
Before last update, my code was working as expected but since the update in version 2.6.0, it don't work.
Perhaps I don't use the library as expected. I changed my code to fit your retry development. My actual code is :
this.uploadsProgress.subscribe((item: UploadState) => {
if (item.status == 'retry' && item.response.message && item.response.message == "Token not valid") {
this.authenticationService.refresh().subscribe(() => {
this.uploadService.control({
action: 'refreshToken',
token: localStorage.getItem('accessToken')
});
});
return;
}
---
});
Is it correct?
All upload requests are sent with the same (old) token.
Does the problem come from the library or from my code?
Thanks in advance for your response
Virginie
I think is better only put as queue the uploads than are in pause (not the uploading ones) and then call the processQueue()
PD: I can do it, but I'am asking for see what was the initial idea with that action
This master issue contains a list of Renovate updates and their statuses.
These branches will be created by Renovate only once you click their checkbox below.
eslint
, eslint-config-prettier
, eslint-plugin-import
, eslint-plugin-prettier
)gh-got
, got
)eslint
, eslint-config-airbnb-base
)These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
ngx-uploadx/src/uploadx/lib/uploader.ts
Lines 267 to 270 in 8e600dc
TODO
comment in 8e600dc when #251 was merged. cc @kukhariev.If you disable autoUpload and use the action 'uploadAll', the url to put the file is always undefined. There is no post request to create a session.
My Options are
this.options = {
concurrency: 2,
allowedTypes: '*',
url: '/services/api/upload/register',
token: 'someToken',
autoUpload: false,
withCredentials: true,
chunkSize: 1024 * 16 * 8,
headers: (f: File) => ({
'Content-Disposition': `filename=${encodeURI(f.name)}`
})
};
Version 2.2.0
Describe the bug
This is a strange one, this hasn't been a problem until very recently but also not sure exactly when it began.
Only happens for configuration/AOT built angular (ie ng build --configuration=dev etc.). Doesn't happen when using app via "ng serve".
I use PrimeNG's fileupload component combined with ngx-uploadx UploadService.
Did some simple debugging with console.log messages:
this.options = {
endpoint: APP_CONFIG.apiEndpoint + '/api/v1/document/docFileUploadInit',
chunkSize: 2097152,
concurrency: 5,
uploaderClass: UploaderXCustom,
autoUpload: false,
token: () => this.authService.getToken()
};
this.uploadService.init(this.options).subscribe((item: UploadState) => {
console.log(JSON.stringify(item, null, 2));
...
});
When local via ng serve (this is where things work normally):
{
"file": {},
"name": "dummy2.txt",
"size": 10485760,
"status": "added",
"uploadId": "f02b88a6",
"url": ""
}
{
"file": {},
"name": "dummy2.txt",
"size": 10485760,
"status": "queue",
"uploadId": "f02b88a6",
"url": ""
}
{
"file": {},
"name": "dummy2.txt",
"responseStatus": 0,
"size": 10485760,
"status": "uploading",
"uploadId": "f02b88a6",
"url": ""
}
{
"file": {},
"name": "dummy2.txt",
"progress": 6.41,
"remaining": 67,
"responseStatus": 0,
"size": 10485760,
"speed": 147798,
"status": "uploading",
"uploadId": "f02b88a6",
"url": "https://localhost:44356/api/v1/document/docFileUpload?tokenId=51baf61c-9284-47e7-9c3f-137bbc1f8be5"
}
{
"file": {},
"name": "dummy2.txt",
"progress": 40,
"remaining": 11,
"responseStatus": 0,
"size": 10485760,
"speed": 582704,
"status": "uploading",
"uploadId": "f02b88a6",
"url": "https://localhost:44356/api/v1/document/docFileUpload?tokenId=51baf61c-9284-47e7-9c3f-137bbc1f8be5"
}
{
"file": {},
"name": "dummy2.txt",
"progress": 60,
"remaining": 7,
"responseStatus": 0,
"size": 10485760,
"speed": 644881,
"status": "uploading",
"uploadId": "f02b88a6",
"url": "https://localhost:44356/api/v1/document/docFileUpload?tokenId=51baf61c-9284-47e7-9c3f-137bbc1f8be5"
}
{
"file": {},
"name": "dummy2.txt",
"progress": 80,
"remaining": 4,
"responseStatus": 0,
"size": 10485760,
"speed": 694479,
"status": "uploading",
"uploadId": "f02b88a6",
"url": "https://localhost:44356/api/v1/document/docFileUpload?tokenId=51baf61c-9284-47e7-9c3f-137bbc1f8be5"
}
{
"file": {},
"name": "dummy2.txt",
"progress": 100,
"remaining": 0,
"responseStatus": 0,
"size": 10485760,
"speed": 729444,
"status": "uploading",
"uploadId": "f02b88a6",
"url": "https://localhost:44356/api/v1/document/docFileUpload?tokenId=51baf61c-9284-47e7-9c3f-137bbc1f8be5"
}
{
"file": {},
"name": "dummy2.txt",
"progress": 100,
"remaining": 0,
"response": 1274303,
"responseStatus": 200,
"size": 10485760,
"speed": 729444,
"status": "complete",
"uploadId": "f02b88a6",
"url": "https://localhost:44356/api/v1/document/docFileUpload?tokenId=51baf61c-9284-47e7-9c3f-137bbc1f8be5"
}
When running via angular-http-server on a ng build --configuration=dev build (AOT, etc.):
{
"file": {},
"name": "dummy2.txt",
"size": 10485760,
"status": "added",
"uploadId": "182e259e",
"url": ""
}
{
"file": {},
"name": "dummy2.txt",
"size": 10485760,
"status": "queue",
"uploadId": "182e259e",
"url": ""
}
{
"file": {},
"name": "dummy2.txt",
"responseStatus": 0,
"size": 10485760,
"status": "uploading",
"uploadId": "182e259e",
"url": ""
}
{
"file": {},
"name": "dummy2.txt",
"progress": 100,
"remaining": 0,
"response": 1274303,
"responseStatus": 200,
"size": 10485760,
"status": "complete",
"uploadId": "182e259e",
"url": "https://localhost:44356/api/v1/document/docFileUpload?tokenId=39aafa11-20e1-469c-80f6-b12831915c59"
}
For some reason the progress events are skipped right over. Also happens on our deployed Azure DEV environment. It otherwise behaves exactly as it should - the same number of requests, responses, chunks, etc. Just no progress states emitted. Basically the only issue is my progress bar UI no longer shows anything. It just sits at 0% until final chunk is sent when it jumps to 100%.
At first I tried reverting to the default uploaderClass (I had it overridden with my own) by not defining one in UploadxOptions - and altered my server responses to be compatible. No luck.
Then I updated ngx-uploadx from 3.1.4 to 3.3.3. No luck.
To Reproduce
Not sure it'd be worth trying to reproduce my exact scenario as it's kind of involved, more looking for advice / whether anyone has seen anything like this.
Setup details:
ngx-uploadx
: 3.1.4 (later updated to 3.3.3)Additional context
Strangely seems independent of any relevant version changes/etc., but not 100% sure here.
If an upload is cancelled, it should not have 'zombie' files at the server
If the cancel or cancelAll action is called, the service should send a 'delete' request for each file to same url like the upload is sent. This sould also be sent, if the file is uploaded complete and the file stays in the queue.
Hi
I need many multiple uploader , per my categories.
How can I set directives id dynamically
I used upload directive in *ngFor , but directives id confilicted:
my Code :
<div *ngFor="let item of categories">
<h3>{{item.name}}</h3>
<input
[attr.id]="item.id"
(click)="???????????.value = ''" // <== My problem is here
(state)="onStateChanged($event)"
[control]="control"
[uploadx]="tusoptions"
id="{{item.id}}"
type="file"
class="file_select"
/>
</div>
What to write in ???????? place?
Is your feature request related to a problem? Please describe.
I'm not able to overwrite the getResponseBody method in my uploaderClass which extends the "Uploader" class.
Describe the solution you'd like
Make getResponseBody public to be able to take full control over the response body parsing on uploader class level.
Describe alternatives you've considered
Handle such behaviour on upload item level (not prefered) :)
Additional context
I've used the MultiPartFormData example within the "upload-examples" to demonstrate this.
export class MultiPartFormData extends Uploader {
responseType = 'json' as XMLHttpRequestResponseType;
private getResponseBody(xhr: any) {
let body: UploadAttachmentFilesResponse[] =
'response' in xhr ? xhr.response : xhr.responseText;
if (body && this.responseType === 'json' && typeof body === 'string') {
try {
body = JSON.parse(body);
} catch (_a) {}
}
return body
}
async getFileUrl(): Promise<string> {
this.offset = 0;
const formData: FormData = new FormData();
formData.append('files', this.file, this.file.name);
await this.request({
method: 'POST',
body: formData,
url: this.endpoint,
progress: true
});
this.offset = this.size;
const location = this.getValueFromResponse('location');
return location ? resolveUrl(location, this.endpoint) : '';
}
async sendFileContent(): Promise<number | undefined> {
return this.size;
}
async getOffset(): Promise<number | undefined> {
return 0;
}
}
Cheers :)
If you use autoupload, then it's not possible to remove the file from the uploaded file list if the upload is complete.
Is there a way to change the default request method from POST to PUT?
Describe the bug
When the server returns 500 upon file upload (PUT request) there's infinite retries.
To Reproduce
this.uploadService.handleFiles(file, {
endpoint: `${environment.apiUrl}/api/v1/videos/upload?uploadType=multipart`,
multiple: false,
token: this.authService.getAccessToken(),
})
And then return 500 when the last part has been uploaded.
Expected behavior
A clear and concise description of what you expected to happen.
Setup details:
ngx-uploadx
: 4.0.2Additional context
When I'm debugging the code it looks like line 136 is reached before the server responded with 500.
ngx-uploadx/src/uploadx/lib/uploader.ts
Lines 131 to 136 in 8213d9f
It's very useful for libraries like this one to include a changelog that helps with migration. I was just upgrading from 3.4 to 3.5 and that has breaking changes that are not documented.
Describe the solution you'd like
A Changelog file with a description of the updates and the breaking changes.
Describe alternatives you've considered
I have to read the code to understand how to migrate my code.
Additional context
Thanks!
Following setup steps produce such error
ngx-uploadx.js:700 Uncaught TypeError: Object(...) is not a function at ngx-uploadx.js:700 at Object../node_modules/ngx-uploadx/fesm5/ngx-uploadx.js (ngx-uploadx.js:706) at __webpack_require__ (bootstrap:76) at Object../src/app/app.module.ts (app.component.ts:9) at __webpack_require__ (bootstrap:76) at Object../src/main.ts (environment.ts:10) at __webpack_require__ (bootstrap:76) at Object.0 (main.ts:12) at __webpack_require__ (bootstrap:76) at checkDeferredModules (bootstrap:43)
Getting following error when trying to implement ngx-uploadx in angular 7 project.
ngx-uploadx/src/uploadx/lib/uploader.ts
Lines 134 to 137 in 8d875c1
TODO
comment in 8d875c1. It's been assigned to @kukhariev because they committed the code.ngx-uploadx/src/uploadx/lib/uploader.ts
Lines 267 to 270 in 8bfaa1c
TODO
comment in 8bfaa1c. It's been assigned to @kukhariev because they committed the code.Hi,
I have a question about access token. When a user is authenticated, a token is sent. On my server, the validity of this token is 5min. Every 5 min, a request to refresh the token is sent to the server.
Is it possible to update the token in the service?
I go through the source code but I don't see anything for it. I would like to send the new token to the service and this token will be used for all following request.
The other thing that will be useful is to retry on failed upload after an error due to an old token.
Is it possible to do something like that with your library? If yes, how?
Thanks in advance for your response
Virginie
The implementation of #20 is not working.
The "_status" (Line 2 in example) variable in the code is not in state "cancelled" if you cancel an upload.
If you cancel an uploading file the is the state 'uploading'. Tested with latest Chrome and Firefox.
return new Promise(function (resolve, reject) {
if (_this.URI && _this._status === 'cancelled') {
/** @type {?} */
var xhr_2 = XHRFactory.getInstance();
xhr_2.open('DELETE', _this.URI, true);
xhr_2.responseType = 'json';
xhr_2.withCredentials = _this.options.withCredentials;
_this.setCommonHeaders(xhr_2);
xhr_2.onload = xhr_2.onerror = function () {
_this.responseStatus = xhr_2.status;
_this.response = parseJson(xhr_2) || {
status: {
code: +xhr_2.status,
message: xhr_2.statusText
}
};
XHRFactory.release(xhr_2);
resolve();
};
xhr_2.send();
}
else {
resolve();
}
});
Hello,
i have installed ngx-uploadx in my angular project, but after installing it, my app stopped working.
After searching the internet i found that this plugin might have issue with my angular version.
in package.json
"@angular/core": "5.2.0", "ngx-uploadx": "^2.4.5",
if to run app with this plugin, if i need to downgrade ngx-uploadx plugin please provide me version number with that i can use this plugin in my angular 5 project
Errors coming on ng serve pasting here:
Describe the bug
If we try to upload the same file in two different tabs of same window It considers the 2nd file same as the first and shows the same progress for both(try to upload large file).
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Both pages should show actual upload progress.
Setup details:
ngx-uploadx 4.0.1
Angular 7.3.10
Firefox
on windows 10
node-uploadx 3.0.0
There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.
Error type: baseBranch not found
Message: The following configured baseBranch could not be found: next
in uploaderx.ts, getOffsetFromResponse doesn't seem to be behaving quite right for the following use cases.
Missing Range: this should be allowed, using the same Google Doc upload reference (https://developers.google.com/drive/api/v3/manage-uploads#resume-upload) that you are using. This should tell the service that no content has been received and to start at byte 0.
"Range: bytes=0-1" : This will get matched as "-1" and will send from byte 0. There's not really a standard on using the Range header on a response, so not sure of what the right answer is. Possible solution would be looking for two dashes when matching "-1", ie, "-1--1" for no content. /(--1|\d+)$/g
Also looking for just "-1", like "Range: bytes=-1" could work.
https://github.com/kukhariev/ngx-uploadx/blob/master/src/uploadx/src/uploaderx.ts
Is your feature request related to a problem? Please describe.
I would like to have a way to specify a certain timeout for a chunk, after which it should be retried.
Describe the solution you'd like
A chunkTimeout
option, in seconds. If a PATCH request doesn't get a response from the server in that time, the chunk should be retried.
Describe alternatives you've considered
None.
Additional context
None.
Thanks!
Dropped support for Angular <7.x. Please upgrade.
Removed uploadAll
, cancelAll
, pauseAll
from type UploadAction
.
Directive properties:
@Output() uploadxState: EventEmitter<Observable<UploadState>>
has been with@Output() state: EventEmitter<UploadState>
@Input() uploadxAction: UploadxControlEvent
to @Input() control: UploadxControlEvent
Before:
// ngx-uploadx v3.x
import { Observable } from 'rxjs';
import { UploadxOptions, UploadState } from 'ngx-uploadx';
@Component({
selector: 'app-home',
templateUrl: `
<input type="file"
[uploadx]="options"
(uploadxState)="onUpload($event)"
[uploadxAction]="control">
`
})
export class AppHomeComponent {
control: UploadxControlEvent;
options: UploadxOptions = { endpoint: `[URL]` };
onUpload(state$: Observable<UploadState>) {
state$.subscribe((state: UploadState) => {
console.log(state);
//...
});
}
cancelAll() {
this.control = { action: 'cancelAll' };
}
}
After:
// ngx-uploadx v4.x
import { UploadxOptions, UploadState } from 'ngx-uploadx';
@Component({
selector: 'app-home',
templateUrl: `
<input type="file"
[uploadx]="options"
(state)="onUpload($event)"
[control]="control">
`
})
export class AppHomeComponent {
options: UploadxOptions = { endpoint: `[URL]` };
onUpload(state: UploadState) {
console.log(state);
//...
}
cancelAll() {
this.control = { action: 'cancel' };
}
}
Renamed type RequestParams
to RequestOptions
.
Removed obsolete setAuth()
method, use new option authorize
instead.
Chocobozzz/PeerTube#4382
There is a issue with File API on these devices. The file stops being read after 60 seconds.
ngx-uploadx/src/uploadx/lib/uploader.ts
Lines 256 to 263 in 48e3756
If you call a cancel, cancelAll, pause oder pauseAll Action and the queue item where the action is applied is not in uploading state, there is an error "abort is not function".
The problem is in the "uploader.ts" line: 45. It's look like the the problem is created in line 71. The new object has no abort() function in the state object.
Version 2.2.0
Browser: Chrome
const UPLOAD_DIR = `/Users/hkhurshudyan/Desktop/graxanut/server/files`;
return {
directory: UPLOAD_DIR,
allowMIME: ['video/*', 'image/*', 'application/epub+zip', 'application/zip'],
path: '/files',
onComplete: async file => {
return new Promise((resolve, reject) => {
resolve('done')
})
}
};
}
it's for server part and this for frontend
``` allowedTypes: 'image/*, application/epub+zip, application/zip',
It's uploads file but it's size 0 byte and I can open it
I'm attempting to use your module (the service specifically) alongside the PrimeNG fileupload component ( https://www.primefaces.org/primeng/#/fileupload ) to give me chunking functionality. It appears to send the initial request to the configured url ( UploadxOptions.url ), but the following PUT requests that happen here:
Uploader.prototype.sendFile = function (start) {
...
xhr.open('PUT', this.url, true);
...
}
have this.url as null. Also tried setting the url in the control methods "itemOptions" parameter, but no luck there.
I'm not sure if this is a bug, or perhaps that am I using the service in a way you didn't intend. Is the intent that the initial POST call and the subsequent PUT calls hit the same apiUrl/method?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.