Comments (4)
possible implementation
import { Metadata, Uploader } from 'ngx-uploadx';
export interface S3SigObject {
chunkSize: number;
url: string;
uploadId: string;
urls: string[];
parts: Part[];
metadata: Metadata;
}
interface Part {
ETag: string;
PartNumber: number;
}
export class S3 extends Uploader {
s3Sig = { metadata: this.metadata } as S3SigObject;
protected async getFileUrl(): Promise<string> {
this.offset = 0;
await this._serverRequest(this.endpoint);
this.chunkSize = this.s3Sig.chunkSize;
return this.s3Sig.url;
}
protected async sendFileContent(): Promise<number> {
const index = this.s3Sig.parts.length;
const { body, end } = this.getChunk();
await this.request({ method: 'PUT', body, url: this.s3Sig.urls[index] });
const etag = this.getValueFromResponse('etag') || '';
const part: Part = { ETag: etag, PartNumber: index + 1 };
this.s3Sig.parts = [...this.s3Sig.parts, part];
if (end === this.size) {
await this._serverRequest(this.url);
return end;
}
return end + 1;
}
protected async getOffset(): Promise<number | undefined> {
await this._serverRequest(this.url);
return Math.min(this.s3Sig.parts.length * this.chunkSize, this.size);
}
private async _serverRequest(url: string): Promise<S3SigObject> {
const body: FormData = new FormData();
body.set('s3Sig', JSON.stringify(this.s3Sig));
await this.request({
method: 'POST',
body,
url
});
return (this.response as object) as S3SigObject;
}
}
But first we need a smart server API...
from ngx-uploadx.
possible implementation
import { Metadata, Uploader } from 'ngx-uploadx'; export interface S3SigObject { chunkSize: number; url: string; uploadId: string; urls: string[]; parts: Part[]; metadata: Metadata; } interface Part { ETag: string; PartNumber: number; } export class S3 extends Uploader { s3Sig = { metadata: this.metadata } as S3SigObject; protected async getFileUrl(): Promise<string> { this.offset = 0; await this._serverRequest(this.endpoint); this.chunkSize = this.s3Sig.chunkSize; return this.s3Sig.url; } protected async sendFileContent(): Promise<number> { const index = this.s3Sig.parts.length; const { body, end } = this.getChunk(); await this.request({ method: 'PUT', body, url: this.s3Sig.urls[index] }); const etag = this.getValueFromResponse('etag') || ''; const part: Part = { ETag: etag, PartNumber: index + 1 }; this.s3Sig.parts = [...this.s3Sig.parts, part]; if (end === this.size) { await this._serverRequest(this.url); return end; } return end + 1; } protected async getOffset(): Promise<number | undefined> { await this._serverRequest(this.url); return Math.min(this.s3Sig.parts.length * this.chunkSize, this.size); } private async _serverRequest(url: string): Promise<S3SigObject> { const body: FormData = new FormData(); body.set('s3Sig', JSON.stringify(this.s3Sig)); await this.request({ method: 'POST', body, url }); return (this.response as object) as S3SigObject; } }But first we need a smart server API...
Just remove the "+ 1" on "return end + 1"
from ngx-uploadx.
updated version:
import { store, UploaderX } from 'ngx-uploadx';
export interface S3Multipart {
partSize: number;
name: string;
UploadId: string;
partsUrls: string[];
Parts?: Part[];
}
interface Part {
ETag: string;
PartNumber: number;
}
export class UploaderXS3 extends UploaderX {
s3 = {} as S3Multipart;
async getFileUrl(): Promise<string> {
const url = await super.getFileUrl();
if (this.response?.partSize) {
this.s3 = { ...this.response };
this.s3.Parts ??= [];
store.set(url, JSON.stringify(this.s3));
this.offset = this.s3.Parts.length * this.s3.partSize;
if (this.s3?.partsUrls.length === this.s3?.Parts.length) {
await this.setMetadata(this.url);
}
}
return url;
}
async sendFileContent(): Promise<number | undefined> {
if (this.s3.partsUrls) {
this.s3.Parts ??= [];
const i = this.s3.Parts.length;
const { body, end } = this.getChunk(this.offset, this.s3.partSize);
await this.request({
method: 'PUT',
body,
url: this.s3.partsUrls[i],
skipAuthorization: true
});
const ETag = this.getValueFromResponse('etag');
if (!ETag) {
return this.offset;
}
const part: Part = { ETag, PartNumber: i + 1 };
this.s3.Parts.push(part);
if (end === this.size) {
await this.setMetadata(this.url);
}
return end;
} else {
return super.sendFileContent();
}
}
async getOffset(): Promise<number | undefined> {
const _s3 = store.get(this.url);
if (_s3) {
this.s3 = JSON.parse(_s3);
await this.setMetadata(this.url);
if (this.response.UploadId) {
this.s3 = { ...this.response };
}
this.s3.Parts ??= [];
return Math.min(this.s3.Parts.length * this.s3.partSize, this.size);
}
return super.getOffset();
}
private async setMetadata(url: string): Promise<S3Multipart> {
const body = JSON.stringify(this.s3);
await this.request({
method: 'PATCH',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body,
url
});
if (this.response?.partsUrls) {
this.s3 = { ...this.response };
}
return this.s3;
}
}
from ngx-uploadx.
For proper operation, at least "exposeHeaders" : ["etag"]
and "AllowedMethods": ["PUT"]
must be set in the cors configuration.
b2 example:
[
{
"corsRuleName": "ngx-uploadx",
"allowedOrigins": [
"*"
],
"allowedHeaders": [
"*"
],
"allowedOperations": [
"s3_put"
],
"exposeHeaders": ["etag"],
"maxAgeSeconds": 3600
}
]
from ngx-uploadx.
Related Issues (20)
- Uploading of same file simultaneously in two different tabs of same window is failing HOT 3
- Window is not defind with Server Side Rendering HOT 1
- Location Error HOT 5
- Infinite retries upon 500 response HOT 4
- Feature request: maxChunkSize HOT 2
- Chunk timeout HOT 4
- Big files upload error with iOS HOT 3
- dynamic directive id HOT 1
- How is re-uploading resumed? HOT 2
- uploading the same file should be faster HOT 4
- why not use real filename for completed uploading HOT 2
- custom metadata is not working well HOT 2
- How to confirm before uploading via drop and drop HOT 2
- Support Angular 13 HOT 1
- How to append additional params to the request (service)? HOT 1
- throw error on using ngx-uploadx and uploadx-server with s3 HOT 1
- How to handle complete response HOT 2
- Drag and drop directory for upload
- Release date of next version HOT 1
- missing Metadata member HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ngx-uploadx.