Multiple file Uploading & downloading


#1

Multiple file Uploading & downloading

    $scope.files.forEach(function (file, index) {            
        camForm.variableManager.createVariable({
        name: 'DOCUMENT_' + index,
        type: 'Bytes',
        value: file.data
          });
    });

We are able to upload multiple files by using the above mentioned code.But some issues are there .
In database(in the table ACT_RU_VARIABLE), it stores data but when compare to single file upload, fields TEXT_ & TEXT2_ are having null values.

To download these uploaded files. We have created another form in the next process

            for(var i=0;i<$scope.fileCount; i++){
                            y = document.createElement("a");
                            y.setAttribute("cam-file-download", "DOCUMENT_"+i);
                            y.setAttribute("href"," /camunda/api/engine/engine/default/task/"+camForm.taskId+"/variables/DOCUMENT_"+i+"/data");
                            y.innerHTML="download"+i;
                            document.getElementById('fileDownloads').appendChild(y);
                     }

It works and we are able to download all files. But still there is no option for identifying the files with name.
From the above code files are downloading as “data” named files. Actually i want to see the original file-name when downloading.


#2

Hi,

you are storing the file contents as variable of type Bytes. This variable type does not have the file name information. You can consider storing the file as a File object instead, see this list of possible value types.

Cheers
Sebastian


#3

Hi @sebastian.stamm , Thanks for your reply.

As per your suggestion i have tried to add variable as file type but i have encountered some issue. I am getting null pointer exception…

Is there any additional things we need to do ?

Regards
Manmohan


#4

Are you using an embedded form? If so, the content of the file needs to be base64-encoded when it is send via the normal submit task form query. You can have a look at how Tasklist is doing that when using the cam-variable-name directive here.

Alternatively, you can also upload files separately from the form lifecycle as described here.


#5

Hi @sebastian.stamm ,

I have tried to encode file data as Base64 . My code snippet is as follows :

//This function will call when we upload files 

    $scope.upload = function(fileUpload) {
         fileUploadCount=fileUpload.files.length;
        for (var i = 0; i < fileUpload.files.length; i++) {
          var file = fileUpload.files[i];    
          $scope.retrieveFiledata(fileUpload.files[i], file);
         $scope.files.push(file);
        }
      };  


//This is used to encode file data to Base64

 $scope.retrieveFiledata = function (file, fileData) {
   var reader = new FileReader();
  reader.onload = function (event) {
  var binaryString = event.target.result;
  fileData.data=btoa(binaryString);
    };
       reader.readAsBinaryString(fileData);
    }


//This is used to create variables 

 
            camForm.on('submit', function() {    
         for(var i=0;i<$scope.files.length;i++){
          camForm.variableManager.createVariable({
            name: 'AXXX' + i,
            type: 'File',
            value: $scope.files[i].data
          });

Log :

01-Dec-2016 15:57:00.949 WARNING [http-nio-192.168.180.122-8080-exec-6] org.camunda.bpm.engine.rest.exception.ExceptionHandler.toResponse java.lang.NullPointerException
at org.camunda.bpm.engine.variable.impl.type.FileValueTypeImpl.createValue(FileValueTypeImpl.java:44)
at org.camunda.bpm.engine.rest.dto.VariableValueDto.toTypedValue(VariableValueDto.java:123)
at org.camunda.bpm.engine.rest.dto.VariableValueDto.toMap(VariableValueDto.java:146)
at org.camunda.bpm.engine.rest.sub.task.impl.TaskResourceImpl.submit(TaskResourceImpl.java:108)
at sun.reflect.GeneratedMethodAccessor555.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:167)
at org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:257)
at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:222)
at org.jboss.resteasy.core.ResourceLocator.invokeOnTargetObject(ResourceLocator.java:159)
at org.jboss.resteasy.core.ResourceLocator.invoke(ResourceLocator.java:107)
at org.jboss.resteasy.core.ResourceLocator.invokeOnTargetObject(ResourceLocator.java:154)
at org.jboss.resteasy.core.ResourceLocator.invoke(ResourceLocator.java:92)
at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:542)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:524)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:126)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.camunda.bpm.engine.rest.filter.CacheControlFilter.doFilter(CacheControlFilter.java:41)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.camunda.bpm.webapp.impl.security.filter.SecurityFilter.doFilterSecure(SecurityFilter.java:67)
at org.camunda.bpm.webapp.impl.security.filter.SecurityFilter.doFilter(SecurityFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.camunda.bpm.webapp.impl.security.auth.AuthenticationFilter$1.execute(AuthenticationFilter.java:59)
at org.camunda.bpm.webapp.impl.security.auth.AuthenticationFilter$1.execute(AuthenticationFilter.java:56)
at org.camunda.bpm.webapp.impl.security.SecurityActions.runWithAuthentications(SecurityActions.java:38)
at org.camunda.bpm.webapp.impl.security.auth.AuthenticationFilter.doFilter(AuthenticationFilter.java:56)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1527)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1484)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

Can you please specify where could i went wrong.


#6

My guess is that you need to set the valueInfo attribute of the variable when you create it. Check out the documentation of the request body for the submit task form query and make sure that you are sending the data according to that specification.

If there are differences, you can try to setup an example using a single file upload form field and compare the payload to your solution.


#7

@sebastian.stamm . Thank you very much.

I have added valueInfo attribute. Now I am able to download the file as its original name. But one more issue is remaining.

when i am using the below mentioned tag, it shows the file name and can be download it.

<a cam-file-download="DOCUMENT_0"></a>

But when i am trying to add this tag dynamically, it doesn’t shows the file name, but it can be downloaded as its original file name

I am using the below mentioned code.

    var y ;
                    
                    for(var i=0;i<$scope.fileCount; i++)
                    {
                        y = document.createElement("a");
                        y.setAttribute("cam-file-download", "DOCUMENT_"+i);
                        y.setAttribute("href"," /camunda/api/engine/engine/default/task/"+camForm.taskId+"/variables/DOCUMENT_"+i+"/data");
                    //    y.innerHTML="download"+i+"<br/>";
                        document.getElementById('fileDownloads').appendChild(y);
                        
                    }

#8

Cool, I am glad to hear that you got the upload working. I am afraid you cannot use the cam-file-download attribute in this way. The reason for that is, that the form is parsed for this attribute when it is initially loaded, so that the request, which fetches all the variables, can also retrieve the file name of the download.

Since you are setting this attribute after the variables are already fetched, the form does not have this information to display. So you would need to fetch this information manually. You can use the Get Task Form Variables endpoint for that.


#9

@sebastian.stamm

We have tried to encode data by using the below mentioned code. It shows incorrect data when downloading.

eg:content of a text file-> [object ArrayBuffer]

    $scope.files = [];
    var fileUploadCount;
    $scope.upload = function(fileUpload) {
        fileUploadCount=fileUpload.files.length;
        for (var i = 0; i < fileUpload.files.length; i++) {
        var file = { name: fileUpload.files[i].name, mimetype: fileUpload.files[i].type, data: undefined};
        $scope.retrieveFiledata(fileUpload.files[i], file);
        }
        $scope.$apply();
     
      };
      
       $scope.removeDocument = function (file) {
       $scope.files.splice($scope.files.indexOf(file), 1);
      };
        $scope.retrieveFiledata = function (file, fileData) {
        var reader = new FileReader();
        reader.onload = function (event) {
        fileData.blob = reader.result;
        var binaryString = event.target.result;
        fileData.data = btoa(binaryString);
        $scope.files.push(fileData);
        };
        reader.readAsArrayBuffer(file);
      };

#10

@sebastian.stamm

Issue has been solved now…

I have edited the code [quote=“manmohanm, post:9, topic:2157”]
reader.readAsArrayBuffer(file);
[/quote]

as

reader.readAsBinaryString(file);


#11

Hi Manmohanm

I tried to download the attachments (Multiple Attachments) in the next task but does not working please help me for that or share the source code with me .

First Task ::

inject(['$http', 'Uri', function($http, Uri) {
  var i=0;
  $scope.upload = function() { 
      i++;
      var y = document.createElement("input");
	  y.setAttribute("id", "fileU");

y.setAttribute(“type”, “file”);
y.setAttribute(“cam-variable-name”, “attachemnt1”);
y.setAttribute(“cam-variable-type”, “File”);
y.setAttribute(“cam-max-filesize”, “10000000”);
y.setAttribute(“ng-model”, “attachemnt1”);

document.getElementById(‘fildUploads’).appendChild(y);
}
}]);
What can i mention in the next task …

Regards
Suhaib Sultan


#12

Hi @manmohanm,

Could you please help me with the valueInfo attribute. I am doing the same but it’s not saving the filename. I am giving like this:
camForm.on(‘submit’, function() {
$scope.files.forEach(function (file, index) {
camForm.variableManager.createVariable({
name: ‘DOCUMENT_’ + index,
type: ‘Bytes’,
value: file.data,
valueInfo: {
filename: file.name,
mimetype: file.type

        }
      });
    });
  });