2021-08-05 13:48:25 +00:00
|
|
|
import HTTPService from 'services/HTTPService';
|
|
|
|
import { getEndpoint } from 'utils/common/apiUtil';
|
|
|
|
import { getToken } from 'utils/common/key';
|
|
|
|
import { logError } from 'utils/sentry';
|
2021-08-11 08:00:59 +00:00
|
|
|
import { UploadFile, UploadURL } from './uploadService';
|
2021-08-05 13:48:25 +00:00
|
|
|
import { File } from '../fileService';
|
2021-08-09 09:26:49 +00:00
|
|
|
import { CustomError } from 'utils/common/errorUtil';
|
2021-08-10 05:35:45 +00:00
|
|
|
import { retryAsyncFunction } from 'utils/network';
|
2021-08-13 06:18:03 +00:00
|
|
|
import { MultipartUploadURLs } from './multiPartUploadService';
|
2021-08-05 13:48:25 +00:00
|
|
|
|
|
|
|
const ENDPOINT = getEndpoint();
|
|
|
|
const MAX_URL_REQUESTS = 50;
|
|
|
|
|
2021-08-13 06:22:18 +00:00
|
|
|
class UploadHttpClient {
|
2021-08-11 04:46:06 +00:00
|
|
|
private uploadURLFetchInProgress = null;
|
2021-08-05 13:48:25 +00:00
|
|
|
|
2021-08-11 04:46:06 +00:00
|
|
|
async uploadFile(uploadFile: UploadFile): Promise<File> {
|
2021-08-05 13:48:25 +00:00
|
|
|
try {
|
|
|
|
const token = getToken();
|
|
|
|
if (!token) {
|
|
|
|
return;
|
|
|
|
}
|
2021-08-11 04:46:06 +00:00
|
|
|
const response = await retryAsyncFunction(() =>
|
|
|
|
HTTPService.post(`${ENDPOINT}/files`, uploadFile, null, {
|
2021-08-05 13:48:25 +00:00
|
|
|
'X-Auth-Token': token,
|
2021-08-13 03:38:02 +00:00
|
|
|
})
|
2021-08-11 04:46:06 +00:00
|
|
|
);
|
2021-08-05 13:48:25 +00:00
|
|
|
return response.data;
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'upload Files Failed');
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-11 04:46:06 +00:00
|
|
|
async fetchUploadURLs(count: number, urlStore: UploadURL[]): Promise<void> {
|
2021-08-05 13:48:25 +00:00
|
|
|
try {
|
|
|
|
if (!this.uploadURLFetchInProgress) {
|
|
|
|
try {
|
|
|
|
const token = getToken();
|
|
|
|
if (!token) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.uploadURLFetchInProgress = HTTPService.get(
|
|
|
|
`${ENDPOINT}/files/upload-urls`,
|
|
|
|
{
|
2021-08-11 04:46:06 +00:00
|
|
|
count: Math.min(MAX_URL_REQUESTS, count * 2),
|
2021-08-05 13:48:25 +00:00
|
|
|
},
|
2021-08-13 03:38:02 +00:00
|
|
|
{ 'X-Auth-Token': token }
|
2021-08-05 13:48:25 +00:00
|
|
|
);
|
|
|
|
const response = await this.uploadURLFetchInProgress;
|
|
|
|
urlStore.push(...response.data['urls']);
|
|
|
|
} finally {
|
|
|
|
this.uploadURLFetchInProgress = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return this.uploadURLFetchInProgress;
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'fetch upload-url failed ');
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fetchMultipartUploadURLs(
|
2021-08-13 03:38:02 +00:00
|
|
|
count: number
|
2021-08-05 13:48:25 +00:00
|
|
|
): Promise<MultipartUploadURLs> {
|
|
|
|
try {
|
|
|
|
const token = getToken();
|
|
|
|
if (!token) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const response = await HTTPService.get(
|
|
|
|
`${ENDPOINT}/files/multipart-upload-urls`,
|
|
|
|
{
|
|
|
|
count,
|
|
|
|
},
|
2021-08-13 03:38:02 +00:00
|
|
|
{ 'X-Auth-Token': token }
|
2021-08-05 13:48:25 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
return response.data['urls'];
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'fetch multipart-upload-url failed');
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async putFile(
|
|
|
|
fileUploadURL: UploadURL,
|
|
|
|
file: Uint8Array,
|
2021-08-13 03:38:02 +00:00
|
|
|
progressTracker
|
2021-08-05 13:48:25 +00:00
|
|
|
): Promise<string> {
|
|
|
|
try {
|
2021-08-11 04:46:06 +00:00
|
|
|
await retryAsyncFunction(() =>
|
2021-08-05 13:48:25 +00:00
|
|
|
HTTPService.put(
|
|
|
|
fileUploadURL.url,
|
|
|
|
file,
|
|
|
|
null,
|
|
|
|
null,
|
2021-08-13 03:38:02 +00:00
|
|
|
progressTracker
|
|
|
|
)
|
2021-08-05 13:48:25 +00:00
|
|
|
);
|
|
|
|
return fileUploadURL.objectKey;
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'putFile to dataStore failed ');
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-09 15:15:11 +00:00
|
|
|
async putFilePart(
|
|
|
|
partUploadURL: string,
|
|
|
|
filePart: Uint8Array,
|
2021-08-13 03:38:02 +00:00
|
|
|
progressTracker
|
2021-08-05 13:48:25 +00:00
|
|
|
) {
|
|
|
|
try {
|
2021-08-11 04:46:06 +00:00
|
|
|
const response = await retryAsyncFunction(async () => {
|
|
|
|
const resp = await HTTPService.put(
|
2021-08-09 15:15:11 +00:00
|
|
|
partUploadURL,
|
|
|
|
filePart,
|
|
|
|
null,
|
|
|
|
null,
|
2021-08-13 03:38:02 +00:00
|
|
|
progressTracker
|
2021-08-09 15:15:11 +00:00
|
|
|
);
|
|
|
|
if (!resp?.headers?.etag) {
|
2021-08-11 04:46:06 +00:00
|
|
|
const err = Error(CustomError.ETAG_MISSING);
|
2021-08-09 15:15:11 +00:00
|
|
|
logError(err);
|
|
|
|
throw err;
|
2021-08-05 13:48:25 +00:00
|
|
|
}
|
2021-08-09 15:15:11 +00:00
|
|
|
return resp;
|
|
|
|
});
|
2021-08-10 05:35:45 +00:00
|
|
|
return response.headers.etag as string;
|
2021-08-09 15:15:11 +00:00
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'put filePart failed');
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-11 04:46:06 +00:00
|
|
|
async completeMultipartUpload(completeURL: string, reqBody: any) {
|
2021-08-09 15:15:11 +00:00
|
|
|
try {
|
2021-08-11 04:46:06 +00:00
|
|
|
await retryAsyncFunction(() =>
|
2021-08-09 15:15:11 +00:00
|
|
|
HTTPService.post(completeURL, reqBody, null, {
|
2021-08-05 13:48:25 +00:00
|
|
|
'content-type': 'text/xml',
|
2021-08-13 03:38:02 +00:00
|
|
|
})
|
2021-08-05 13:48:25 +00:00
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'put file in parts failed');
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-09 15:15:11 +00:00
|
|
|
|
2021-08-13 06:22:18 +00:00
|
|
|
export default new UploadHttpClient();
|