added azure related code
[it/otf.git] / otf-frontend / server / src / feathers / services / file-transfer / file-transfer.class.js
index 0ac6670..9638922 100644 (file)
 \r
 const Response = require('http-response-object');\r
 const Readable = require('stream').Readable;\r
-const mongooseGridFS = require('mongoose-gridfs');\r
+const { createModel } = require('mongoose-gridfs');\r
 const AdmZip = require('adm-zip');\r
 const errors = require('@feathersjs/errors');\r
+const mongoose = require('mongoose');\r
+const ObjectID = require('mongodb').ObjectID;\r
+const {\r
+       Aborter,\r
+       BlockBlobURL,\r
+       BlobURL,\r
+       downloadBlobToBuffer,\r
+       uploadStreamToBlockBlob\r
+  } = require("@azure/storage-blob");\r
+\r
 \r
 class Service {\r
        constructor (options) {\r
                this.options = options || {};\r
-               this.mongoose = this.options.app.get('mongooseClient');\r
-               this.gridfs = mongooseGridFS({\r
-                       collection: 'fs',\r
-                       model: 'File',\r
-                       mongooseConnection: this.mongoose.connection\r
-               });\r
-               this.FileModel = this.gridfs.model;\r
+               // this.File = createModel({\r
+               //      collection: 'fs',\r
+               //      model: 'File',\r
+               //      mongooseConnection: mongoose.connection\r
+               // });\r
        }\r
 \r
        async find (params) {\r
@@ -37,14 +45,30 @@ class Service {
        }\r
 \r
        async get (id, params) {\r
-               let content = await this.callReadFile(id).then(res => {\r
-                       return res;\r
-               });\r
-\r
-               if(params.query && params.query.robot){\r
-                       content = await this.createRobotResponse(content);\r
+               if(!id){\r
+                       throw new errors.BadRequest("File id is required");\r
                }\r
-               return content;\r
+\r
+               // Get Blob url\r
+               const blob = BlobURL.fromContainerURL(this.options.app.get('azureStorageContainerUrl'), id);\r
+               const stats = await blob.getProperties().catch(err => {\r
+                       throw new errors.NotFound();\r
+               });\r
+               // const content = await blob.download(Aborter.none, 0);\r
+               const buffer = Buffer.alloc(stats.contentLength);\r
+               await downloadBlobToBuffer(\r
+                       Aborter.timeout(30 * 60 * 1000),\r
+                       buffer,\r
+                       blob,\r
+                       0,\r
+                       undefined,\r
+                       {\r
+                         blockSize: 4 * 1024 * 1024, // 4MB block size\r
+                         parallelism: 20, // 20 concurrency\r
+                       }\r
+                 );\r
+\r
+               return buffer;\r
        }\r
 \r
        async create (data, params) {\r
@@ -54,31 +78,37 @@ class Service {
             throw new BadRequest("No files found to upload")\r
         }\r
 \r
-        let promises = [];\r
-\r
+               let promises = [];\r
+               \r
         files.forEach(file => {\r
-            let promise = new Promise( (resolve, reject) => {\r
-\r
-                let stream = new Readable();\r
-                stream.push(file.buffer);\r
-                stream.push(null);\r
-\r
-               this.FileModel.write(\r
-                       {\r
-                               filename: file.originalname,\r
-                               contentType: file.mimeType\r
-                       },\r
-                       stream,\r
-                       function (error, savedAttachment) {\r
-                               if (error) {\r
-                                       logger.error(error);\r
-                                       reject(error);\r
-                               } else {\r
-                            stream.destroy();\r
-                            resolve(savedAttachment);\r
-                               }\r
-                    }\r
-                );\r
+            let promise = new Promise(async (resolve, reject) => {\r
+\r
+                               let exists, filename, blob, blockBlob;\r
+                               // Creates the file id and checks that there isn't already a file with that name\r
+                               do {\r
+\r
+                                       filename = ObjectID().toString();\r
+                                       \r
+                                       blob = BlobURL.fromContainerURL(this.options.app.get('azureStorageContainerUrl'), filename);\r
+                                       blockBlob = BlockBlobURL.fromBlobURL(blob);\r
+                                       exists = await blockBlob.getProperties().catch(err => {\r
+                                               if(err.statusCode == 404){\r
+                                                       exists = false;\r
+                                               }\r
+                                       });\r
+\r
+                               } while (exists);\r
+       \r
+                               blockBlob.upload(Aborter.none, file.buffer.toString(), file.size).then(\r
+                                       result => {\r
+                                               result._id = filename;\r
+                                               resolve(result);\r
+                                       }\r
+                               ).catch(\r
+                                       error => {\r
+                                               reject(error);\r
+                                       }\r
+                               );\r
 \r
             })\r
 \r
@@ -90,6 +120,8 @@ class Service {
         return result;\r
        }\r
 \r
+       \r
+\r
        async update (id, data, params) {\r
                return new Response(200, {});\r
        }\r
@@ -99,13 +131,13 @@ class Service {
        }\r
 \r
        async remove (id, params) {\r
-               let err = await this.callUnlinkFile(id).then(err => {\r
-            return err;\r
-        });\r
+               // let err = await this.callUnlinkFile(id).then(err => {\r
+        //     return err;\r
+        // });\r
 \r
-        if(err){\r
-            throw errors.GeneralError(err);\r
-        }        \r
+        // if(err){\r
+        //     throw errors.GeneralError(err);\r
+        // }        \r
 \r
         return new Response(200, {});\r
        }\r