Skip to content

Commit

Permalink
Merge pull request #742 from mcneilco/741-acas-forms-blob-value-support
Browse files Browse the repository at this point in the history
741 acas forms blob value support
  • Loading branch information
brianbolt committed May 13, 2021
2 parents ba4d73b + 9602bc3 commit e70daec
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 14 deletions.
4 changes: 2 additions & 2 deletions app_template.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ startApp = ->
app.use flash()
app.use passport.initialize()
app.use passport.session pauseStream: true
app.use(bodyParser.json({limit: '100mb'}))
app.use(bodyParser.urlencoded({limit: '100mb', extended: true,parameterLimit: 1000000}))
app.use(bodyParser.json({limit: '1000mb', extended: true}))
app.use(bodyParser.urlencoded({limit: '1000mb', extended: true,parameterLimit: 1000000}))
app.use(express.static(path.join(__dirname, 'public')))

loginRoutes.setupRoutes(app, passport)
Expand Down
4 changes: 2 additions & 2 deletions modules/CmpdRegBulkLoader/src/client/CmpdRegBulkLoader.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ class DetectSdfPropertiesController extends Backbone.View
@browseFileController.on('fileUploader:uploadComplete', @handleFileUploaded.bind(@))
@browseFileController.on('fileDeleted', @handleFileRemoved.bind(@))

handleFileUploaded: (fileName) =>
@fileName = fileName
handleFileUploaded: (file) =>
@fileName = file.name
@trigger 'fileChanged', @fileName
@getProperties()

Expand Down
87 changes: 83 additions & 4 deletions modules/Components/src/client/ACASFormFields.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ class ACASFormLSLabelFieldController extends ACASFormAbstractFieldController
# thing lsTypeAndKind and label lsTypeAndKind
# If the label text is "" or null then it will set the next auto sequence value
# so in this case its ok to send "" and ignored = false
if value != "" || @getModel.get("isAutoLabel")
if value != "" || @getModel().get("isAutoLabel")
@getModel().set
labelText: value
ignored: false
Expand Down Expand Up @@ -707,6 +707,10 @@ class ACASFormLSFileValueFieldController extends ACASFormAbstractFieldController
_.extend {}, super(),
"click .bv_deleteSavedFile": "handleDeleteSavedFile"

initialize: (options)->
super(options)
@fileURL = UtilityFunctions::getFileServiceURL()

applyOptions: ->
super()
if @options.allowedFileTypes?
Expand Down Expand Up @@ -756,7 +760,7 @@ class ACASFormLSFileValueFieldController extends ACASFormAbstractFieldController
el: @$('.bv_file')
maxNumberOfFiles: 1
requiresValidation: false
url: UtilityFunctions::getFileServiceURL()
url: @fileURL
allowedFileTypes: @allowedFileTypes
hideDelete: false
@fileController.on 'amDirty', =>
Expand All @@ -767,10 +771,10 @@ class ACASFormLSFileValueFieldController extends ACASFormAbstractFieldController
@fileController.on('fileUploader:uploadComplete', @handleFileUpload.bind(@)) #update model with filename
@fileController.on('fileDeleted', @handleFileRemoved.bind(@)) #update model with filename

handleFileUpload: (nameOnServer) =>
handleFileUpload: (file) =>
@clearError()
@getModel().set
value: nameOnServer
value: file.name
ignored: false

disableInput: ->
Expand All @@ -785,6 +789,81 @@ class ACASFormLSFileValueFieldController extends ACASFormAbstractFieldController
@$('.bv_deleteSavedFile').hide()
@createNewFileChooser()


class ACASFormLSBlobValueFieldController extends ACASFormLSFileValueFieldController
###
Launching controller must:
- Initialize the model with an LSValue
- Provide allowedFileTypes
Do whatever else is required or optional in ACASFormAbstractFieldController
###

initialize: (options)->
super(options)
@fileURL = "/blobUploads"

arrayToBase64String: (a)->
btoa new Uint8Array(a).reduce(((data, byte) ->
data + String.fromCharCode(byte)
), '')

setupFileController: ->
fileValue = @getModel().get('value')
if @isEmpty()
@createNewFileChooser()
@$('.bv_deleteSavedFile').hide()
else
displayText = @getModel().get('comments')
if !displayText?
displayText = "InternalErrorUnknownFileName"
id = @getModel().get('id')
# Display inline not supported right now because guessing mimetype from extension isn't available
# so always be falsey here but leaving this in place
if false and @displayInline and @mimeType?
@$('.bv_file').html '<img src="data:' + @mimeType + ';base64,'+@arrayToBase64String(fileValue)+'" alt="'+ displayText+'">'
else
@$('.bv_file').html '<a href="/api/thingvalues/downloadThingBlobValueByID/'+id+'">'+displayText+'</a>'
@$('.bv_deleteSavedFile').show()

setEmptyValue: ->
@getModel().set
value: null
ignored: true

isEmpty: ->
empty = false
mdl = @getModel()
if mdl.get('comments')=="" or !mdl.get('comments')? then empty = true
if mdl.get('ignored') then empty = true
return empty

createNewFileChooser: ->
if @fileController?
@fileController.render()
else
@fileController = new LSFileChooserController
el: @$('.bv_file')
maxNumberOfFiles: 1
requiresValidation: false
url: @fileURL
allowedFileTypes: @allowedFileTypes
hideDelete: false
@fileController.on 'amDirty', =>
@trigger 'amDirty'
@fileController.on 'amClean', =>
@trigger 'amClean'
@fileController.render()
@fileController.on('fileUploader:uploadComplete', @handleFileUpload.bind(@)) #update model with filename
@fileController.on('fileDeleted', @handleFileRemoved.bind(@)) #update model with filename

handleFileUpload: (file) =>
@clearError()
@mimeType = file.mimeType
@getModel().set
value: file.binaryData
comments: file.name
ignored: false

class ACASFormLSBooleanFieldController extends ACASFormAbstractFieldController
###
Launching controller must:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ class AbstractThingFormController extends AbstractFormController
when 'urlValue' then newField = new ACASFormLSURLValueFieldController opts
when 'dateValue' then newField = new ACASFormLSDateValueFieldController opts
when 'fileValue' then newField = new ACASFormLSFileValueFieldController opts
when 'blobValue' then newField = new ACASFormLSBlobValueFieldController opts
when 'booleanValue' then newField = new ACASFormLSBooleanFieldController opts
when 'locationTree'
opts.tubeCode = @model.get('tubeCode')
Expand Down
2 changes: 1 addition & 1 deletion modules/Components/src/client/LSFileChooser.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class LSFileChooserController extends Backbone.View
_.each(data.result.files, (result) ->
self.listOfFileModels.push(new LSFileChooserModel({fileNameOnServer: result.name}))
)
this.trigger('fileUploader:uploadComplete', data.result.files[0].name)
this.trigger('fileUploader:uploadComplete', data.result.files[0])
if (@requiresValidation)
@$('.dv_validatingProgressBar').show("slide")
@delegateEvents()
Expand Down
4 changes: 2 additions & 2 deletions modules/ServerAPI/src/client/AttachFile.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ class BasicFileController extends AbstractFormController
# @lsFileChooser.on('fileDeleted', @handleFileRemoved) #update model with filename
@

handleFileUpload: (nameOnServer) =>
handleFileUpload: (file) =>
if @autoAddAttachFileModel
@$('.bv_delete').show()
@$('td.delete').hide()
@model.set fileValue: nameOnServer
@model.set fileValue: file.name
@trigger 'fileUploaded'
@trigger 'amDirty'

Expand Down
54 changes: 51 additions & 3 deletions modules/ServerAPI/src/server/routes/FileServices.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
serverUtilityFunctions = require './ServerUtilityFunctions.js'

fs = require 'fs'
path = require 'path'
multer = require 'multer'

setupRoutes = (app, loginRoutes, requireLogin) ->
config = require '../conf/compiled/conf.js'
Expand All @@ -21,13 +23,60 @@ setupRoutes = (app, loginRoutes, requireLogin) ->
return
upload.fileHandler() req, res, next

getBlobByteArray = (req, resp) ->

# Configure this route to write posted files to temp files path
tempUploads = multer({dest:tempFilesPath}).any();

# Function to handle request after files have been saved and added
# to the request by multer
tempUploads req, resp, (err) ->
if req.fileValidationError
console.error(err)
return resp.send(req.fileValidationError)
else if !req.files
console.error(err)
return resp.send('Please post a file')
else if err instanceof multer.MulterError
console.error(err)
return resp.send(err)
else if err
console.error(err)
return resp.send(err)
# No errors
else
try
files = []
for file, i in req.files
console.log("Getting binary data for file saved to #{file.path}")
data = fs.readFileSync(file.path)
arrByte= Uint8Array.from(Buffer.from(data))
binaryData= Array.from(arrByte)
outfile = {
"name": file.originalname,
"originalName": file.originalname,
"size": file.size,
"type": file.mimetype,
"deleteType": "DELETE",
"url": "/tempfiles/" + path.basename(file.path),
"binaryData": binaryData
}
files.push(outfile)
resp.json {"files": files}
catch err
console.error(err)
resp.send(err)


app.post '/blobUploads', getBlobByteArray

upload.on "error", (e) ->
console.log "fileUpload: ", e.message
upload.on "end", (fileInfo) ->
console.log fileInfo
app.emit "file-uploaded", fileInfo



serverUtilityFunctions.ensureExists dataFilesPath, 0o0744, (err) ->
if err?
Expand Down Expand Up @@ -55,10 +104,9 @@ setupRoutes = (app, loginRoutes, requireLogin) ->
app.get '/tempfiles/*', (req, resp) ->
resp.sendfile(tempFilesPath + encodeURIComponent(req.params[0]))


exports.setupAPIRoutes = (app, loginRoutes) ->
setupRoutes app, loginRoutes, false
# app.get '/dataFiles/*', (req, resp) ->
# resp.sendfile('/Users/jam/Projects/ACAS/dev/acas-master-dev/acas/privateUploads/'+ req.params[0])

exports.setupRoutes = (app, loginRoutes) ->
setupRoutes app, loginRoutes, true
Expand Down
50 changes: 50 additions & 0 deletions modules/ServerAPI/src/server/routes/ThingServiceRoutes.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ exports.setupAPIRoutes = (app, loginRoutes) ->
app.post '/api/bulkPostThingsSaveFile', exports.bulkPostThingsSaveFile
app.put '/api/bulkPutThingsSaveFile', exports.bulkPutThingsSaveFile
app.delete '/api/things/:lsType/:lsKind/:idOrCodeName', exports.deleteThing
app.get '/api/thingvalues/getThingValueById/:id', exports.getThingValueById
app.get '/api/thingvalues/downloadThingBlobValueByID/:id', exports.downloadThingBlobValueByID


exports.setupRoutes = (app, loginRoutes) ->
Expand Down Expand Up @@ -63,10 +65,55 @@ exports.setupRoutes = (app, loginRoutes) ->
app.post '/api/bulkPostThingsSaveFile', loginRoutes.ensureAuthenticated, exports.bulkPostThingsSaveFile
app.put '/api/bulkPutThingsSaveFile', loginRoutes.ensureAuthenticated, exports.bulkPutThingsSaveFile
app.delete '/api/things/:lsType/:lsKind/:idOrCodeName', loginRoutes.ensureAuthenticated, exports.deleteThing
app.get '/api/thingvalues/getThingValueById/:id', loginRoutes.ensureAuthenticated, exports.getThingValueById
app.get '/api/thingvalues/downloadThingBlobValueByID/:id', loginRoutes.ensureAuthenticated, exports.downloadThingBlobValueByID


request = require 'request'
config = require '../conf/compiled/conf.js'

exports.getThingValueById = (req, resp) ->
exports.getlsValuesByIdInternal req.params.id, req.query, (statusCode, value) ->
resp.statusCode = statusCode
resp.json value

exports.getlsValuesByIdInternal = (id, params, callback) ->
serverUtilityFunctions = require './ServerUtilityFunctions.js'
baseurl = config.all.client.service.persistence.fullpath+"lsthingvalues/"+id
if params? && params.format?
baseurl += "?format=#{params.format}"
serverUtilityFunctions.getFromACASServerInternal baseurl, (statusCode, value) ->
callback(statusCode, value)

exports.downloadThingBlobValueByID = (req, resp) ->
mime = require('mime');
fs = require('fs');
exports.getlsValuesInternal req.params.id, {format: "withblobvalue"}, (statusCode, value) ->
mimetype = mime.lookup(value.comments);
resp.setHeader('Content-disposition', 'attachment; filename=' + value.comments);
resp.setHeader('Content-type', mimetype);
buffer = new Buffer.from(Uint8Array.from(value.blobValue))
stream = exports.bufferToStream(buffer)
stream.on 'data', (chunk) ->
resp.send(chunk);
stream.on 'data', (chunk) ->
resp.status(200).send();

exports.bufferToStream = (buffer) ->
Duplex = require('stream').Duplex
stream = new Duplex
stream.push buffer
stream.push null
stream

exports.getlsValuesInternal = (id, params, callback) ->
serverUtilityFunctions = require './ServerUtilityFunctions.js'
baseurl = config.all.client.service.persistence.fullpath+"lsthingvalues/"+id
if params? && params.format?
baseurl += "?format=#{params.format}"
serverUtilityFunctions.getFromACASServerInternal baseurl, (statusCode, value) ->
callback(statusCode, value)

exports.thingsByTypeKind = (req, resp) ->
if req.query.testMode or global.specRunnerTestmode
thingServiceTestJSON = require '../public/javascripts/spec/testFixtures/ThingServiceTestJSON.js'
Expand Down Expand Up @@ -469,6 +516,7 @@ postThing = (isBatch, req, resp) ->
body: thingToSave
json: true
, (error, response, json) =>

if !error && response.statusCode == 201
req.query.nestedfull=true
getThing req, json.codeName, (thing) =>
Expand All @@ -478,6 +526,8 @@ postThing = (isBatch, req, resp) ->
console.log error
console.log json
console.log response
resp.statusCode = 500
resp.end "got ajax error trying to save lsThing"
)

exports.postThingParent = (req, resp) ->
Expand Down

0 comments on commit e70daec

Please sign in to comment.