Commit 4c9e0ff8 authored by ChakshuGautam's avatar ChakshuGautam
Browse files

File upload

Showing with 21653 additions and 10055 deletions
+21653 -10055
......@@ -152,15 +152,13 @@ async function _uploadBatch(recordBatch, record) {
controller.abort();
}, settings.timeout);
function getMeta(metaName) {
return document.querySelector(`meta[name=${metaName}]`).content;
}
console.log('REC', recordBatch.formData);
const formSpec = getMeta('formSpec');
const formController = new FormController(JSON.parse(formSpec));
const response = await formController.processForm(record.xml);
const response = await formController.processForm(record.xml, record.files);
// TODO: transforrm the form response
// TODO: submit the form
formController.broadcastFormData();
......
import { xml2json } from "./xml2json";
import { xml2json } from './xml2json';
export class FormController {
......@@ -74,13 +74,68 @@ export class FormController {
return this._state;
}
async processForm(formData) {
findKey(obj, val, keyToFind, currentDotNotation) {
if (typeof obj === 'object') {
for (const key in obj) {
if (obj[key] === val && key === keyToFind) {
return currentDotNotation;
} else {
const result = this.findKey(obj[key], val, keyToFind, currentDotNotation + '.' + key);
if (result !== null) return result;
}
}
}
return null;
}
async uploadFile(data) {
const fd = new FormData();
var newFile = new File([data], data.name, { type: data.type });
console.log(newFile);
fd.append('file', newFile, data.name);
const response = await fetch('http://localhost:3002/form/uploadFile', {
method: 'POST',
body: fd
}).then(s => {
return s.json();
}).catch(e => {
console.log(e);
});
return response.fileURL;
}
set(obj, path, value) {
if (Object(obj) !== obj) return obj; // When obj is not an object
// If not yet an array, get the keys from the string-path
if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
path.slice(0, -1).reduce((a, c, i) => // Iterate all of them except the last one
Object(a[c]) === a[c] // Does the key exist and is its value an object?
// Yes: then follow that path
? a[c]
// No: create the key. Is the next key a potential array-index?
: a[c] = Math.abs(path[i + 1]) >> 0 === +path[i + 1]
? [] // Yes: assign a new array object
: {}, // No: assign a new plain object
obj)[path[path.length - 1]] = value; // Finally assign the value to the last key
return obj; // Return the top-level object to allow chaining
}
async processForm(formData, formFiles) {
const doc = this._parser.parseFromString(formData, 'text/xml');
this.formData = (await fetch('http://localhost:3002/form/parse/' + encodeURIComponent(formData)).then(res => res.json())).data;
for (let i = 0; i < formFiles.length; i++) {
const file = formFiles[i];
const fileURL = await this.uploadFile(file);
const kk = this.findKey(this.formData, file.name, '$t', '');
this.formData = this.set(this.formData, kk.substring(1), fileURL);
}
if (await this.formSpec.isSuccessExecute() === true) {
this._state = 'FORM_SUCCESS';
this._onFormSuccessData = await this.formSpec.onFormSuccessExecute();
console.log(this._onFormFailureData);
this._state = 'ON_FORM_SUCCESS_COMPLETED';
this.nextForm = this.formSpec.onSuccess.next;
this._message = this.formSpec.messageOnSuccess;
......
......@@ -32,4 +32,6 @@ lerna-debug.log*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
\ No newline at end of file
!.vscode/extensions.json
.development.env
\ No newline at end of file
This diff is collapsed.
......@@ -22,14 +22,19 @@
},
"dependencies": {
"@nestjs/common": "^8.0.0",
"@nestjs/config": "^2.2.0",
"@nestjs/core": "^8.0.0",
"@nestjs/platform-express": "^8.0.0",
"minio": "^7.0.32",
"reflect-metadata": "^0.1.13",
"request": "^2.88.2",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
"uuid": "^9.0.0",
"webpack": "^5.74.0",
"xmldom": "^0.6.0",
"xml2json": "^0.12.0"
"xml2js": "^0.4.23",
"xml2json": "^0.12.0",
"xmldom": "^0.6.0"
},
"devDependencies": {
"@nestjs/cli": "^8.0.0",
......@@ -37,6 +42,8 @@
"@nestjs/testing": "^8.0.0",
"@types/express": "^4.17.13",
"@types/jest": "27.4.1",
"@types/minio": "^7.0.13",
"@types/multer": "^1.4.7",
"@types/node": "^16.0.0",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
......@@ -71,4 +78,4 @@
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
\ No newline at end of file
}
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
import {
Body,
Controller,
Get,
HttpException,
HttpStatus,
Param,
Post,
Query,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express/multer';
import { AppService } from './app.service';
import { v4 as uuidv4 } from 'uuid';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Minio = require('minio');
import { Client, ItemBucketMetadata } from 'minio';
import { ConfigService } from '@nestjs/config';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const parser = require('xml2json');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const request = require('request');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const xml2js = require('xml2js');
type PrefillDto = {
form: string;
onFormSuccessData: any;
......@@ -12,7 +37,95 @@ type PrefillDto = {
@Controller()
export class AppController {
constructor(private readonly appService: AppService) { }
constructor(
private readonly appService: AppService,
private configService: ConfigService,
) { }
getLoginToken = () => {
try {
const postData = {
loginId: this.configService.get('MINIO_LOGIN_ID'),
password: this.configService.get('MINIO_PASSWORD'),
applicationId: this.configService.get('MINIO_APPLICATION_ID'),
};
const header = {
'content-type': 'application/json',
Authorization: this.configService.get('MINIOT_HEADER_AUTH_TOKEN'),
};
const options = {
method: 'POST',
url: this.configService.get('MINIO_LOGIN_URL'),
headers: header,
json: postData,
};
return new Promise((resolve, reject) => {
request(options, function (error, response, body) {
if (error || !body) {
return reject(error);
}
resolve(body.token);
});
});
} catch (err) {
console.log('Error', err);
throw err;
}
};
getSessionToken = async (logToken) => {
const MINIO = {
BUCKET_ID: this.configService.get('MINIO_BUCKET_ID'),
HOST: this.configService.get('MINIO_HOST'),
};
try {
const options = {
method: 'POST',
url: `https://${MINIO.HOST}/minio/${MINIO.BUCKET_ID}/?Action=AssumeRoleWithWebIdentity&DurationSeconds=36000&WebIdentityToken=${logToken}&Version=2011-06-15`,
};
return new Promise((resolve, reject) => {
request(options, async function (error, response, body) {
if (error || !body) {
return reject(error);
}
const parser = new xml2js.Parser();
const doc = await parser.parseStringPromise(body);
if (
doc &&
doc.AssumeRoleWithWebIdentityResponse &&
doc.AssumeRoleWithWebIdentityResponse
.AssumeRoleWithWebIdentityResult &&
doc.AssumeRoleWithWebIdentityResponse
.AssumeRoleWithWebIdentityResult.length &&
doc.AssumeRoleWithWebIdentityResponse
.AssumeRoleWithWebIdentityResult[0].Credentials &&
doc.AssumeRoleWithWebIdentityResponse
.AssumeRoleWithWebIdentityResult[0].Credentials.length
) {
const creds =
doc.AssumeRoleWithWebIdentityResponse
.AssumeRoleWithWebIdentityResult[0].Credentials[0];
return resolve({
accessKey: creds.AccessKeyId[0],
secretKey: creds.SecretAccessKey[0],
sessionToken: creds.SessionToken[0],
});
}
reject('Body error');
});
});
} catch (err) {
console.log(err);
throw err;
}
};
@Get()
getHello(): string {
......@@ -61,4 +174,49 @@ export class AppController {
parseXML(@Param('xml') xml): any {
return parser.toJson(xml);
}
@Post('form/uploadFile')
@UseInterceptors(FileInterceptor('file'))
async uploadFile(@UploadedFile() file: Express.Multer.File) {
const extension = file.originalname.split('.').pop();
const fileName = uuidv4() + `.${extension}`;
const tokenRes = await this.getLoginToken();
const sessionRes: any = await this.getSessionToken(tokenRes);
console.log('sessionRes', sessionRes);
const minioClient: Client = new Minio.Client({
endPoint: 'cdn.samagra.io',
useSSL: true,
accessKey: sessionRes?.accessKey,
secretKey: sessionRes?.secretKey,
sessionToken: sessionRes?.sessionToken,
});
const metaData: ItemBucketMetadata = {
'Content-Type': file.mimetype,
};
minioClient.putObject(
this.configService.get('MINIO_BUCKET_ID'),
fileName,
file.buffer,
file.size,
metaData,
function (err, res) {
if (err) {
throw new HttpException(
'Error uploading file',
HttpStatus.BAD_REQUEST,
);
}
},
);
const fileURL = `https://cdn.samagra.io/${this.configService.get(
'MINIO_BUCKET_ID',
)}/${fileName}`;
return { fileURL };
}
}
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [],
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.development.env',
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
export class AppModule { }
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment