1

I added flow.js in my proyect following the instructions and the call to my java servlet:

localhost:8080/WebExample/UploadImgServlet?flowChunkNumber=1&flowChunkSize=1048576&flowCurrentChunkSize=693916&flowTotalSize=693916&flowIdentifier=693916-image2png&flowFilename=image2.png&flowRelativePath=image2.png&flowTotalChunks=1`

In my servlet I get all parameters of the url (flowChuckNumber, flowChuckSize, etc) but when I try to get the file (request.getInputStream()), it's empty and upload 0 bytes.

Where is the problem? Any Idea?

I found a similar question but it was with PHP...

My code:

HTML(the image is displayed):

...
...
<div flow-init="{singleFile:true}"
 flow-file-added="!!{png:1,gif:1,jpg:1,jpeg:1}[$file.getExtension()]"
     flow-files-submitted="$flow.upload()"
     flow-file-success="$file.msg = $message">
         <div class="drop" flow-drop ng-class="dropClass">

        <md-button class="md-raised md-primary" type="file" flow-btn>Upload Image</md-button>
    <b>OR</b>
    Drag And Drop your image here
  </div>
    <div class="thumbnail" ng-show="!$flow.files.length">
      <img src="http://www.placehold.it/200x150/EFEFEF/AAAAAA&text=no+image" alt="Image"/>
    </div>
    <div class="thumbnail" ng-show="$flow.files.length">
      <img flow-img="$flow.files[0]" />
    </div>

  <table>
    <tr ng-repeat="file in $flow.files">
        <td>{{$index+1}}</td>
        <td>{{file.name}}</td>
        <td>{{file.msg}}</td>
    </tr>
  </table>
</div>
...
...

App AngularJs:

var app = angular.module("webexample", ['ngMaterial', 'ngNotify','uiGmapgoogle-maps','flow'])
.config(['flowFactoryProvider', function (flowFactoryProvider) {
      flowFactoryProvider.defaults = {
        target: '/WebExample/UploadImgServlet',
        permanentErrors: [404, 500, 501],
        maxChunkRetries: 1,
        chunkRetryInterval: 5000,
        simultaneousUploads: 1
      };
      flowFactoryProvider.on('catchAll', function (event) {
        console.log('catchAll', arguments);
      });
      // Can be used with different implementations of Flow.js
      // flowFactoryProvider.factory = fustyFlowFactory;
    }])
    .directive('appDownloadUrl', [function () {
      return {
        restrict: 'A',
        link: function(scope, element, attrs) {
          element.bind('dragstart', function (event) {
            var config = scope.$eval(attrs.appDownloadUrl);
            if (!config.disabled) {
              var data = config.mime + ':' + config.name + ':' + window.location.href + config.url;
                        console.log("data: "+data);
              event.dataTransfer.setData('DownloadURL', data);
            }
          });
        }
      };
    }])
    .directive("appDragstart", [function () {
      return function(scope, element, attrs) {
        element.bind('dragstart', function (event) {
          scope.$eval(attrs.appDragstart);
        });
      }
    }]).directive("appDragend", [function () {
      return function(scope, element, attrs) {
        element.bind('dragend', function (event) {
          scope.$eval(attrs.appDragend);
        });
      }
    }]).run(function ($rootScope) {
      $rootScope.dropEnabled = true;
    });

My Servlet (I followed this example):

protected void doService(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException
    {
        LOGGER.debug("[UploadImgServlet - doService] - init");

        int resumableChunkNumber  = getResumableChunkNumber(request);

        ResumableInfo info = getResumableInfo(request);
        //info contains all flow parameters of the url.

        RandomAccessFile raf = new RandomAccessFile(info.resumableFilePath, "rw");

        //Seek to position
        raf.seek((resumableChunkNumber - 1) * info.resumableChunkSize);

        //Save to file
        InputStream is = request.getInputStream();
        long readed = 0;

        long content_length = request.getContentLength();
        //**PROBLEM: request.getContentLength return -1 so read 0 bytes**


        byte[] bytes = new byte[1024 * 100];
        while(readed < content_length) {
            int r = is.read(bytes);
            if (r < 0)  {
                break;
            }
            raf.write(bytes, 0, r);
            readed += r;
        }
        raf.close();
...
...
Jose Antonio
  • 578
  • 1
  • 8
  • 34

3 Answers3

2

The input stream will be empty because flowjs posts the content using MultiPart by default. The author of the Java code specified that "Octet" should be used for uploads, not multi-part.

UploadServlet accepts Resumable.js Upload with 'octet'

You need to add "method:octet" to your init,

<div flow-init="{singleFile:true, method:octet}"

I am using Spring, so I just used MultipartHttpServletRequest to get the posted data with MultiPart instead because MultiPart is more common.

This is how I received the contents of the file:

Iterator<String> itr = request.getFileNames();

/* Iterate each file, there should only be one/one chunk */
while (itr.hasNext()) {
    fileUploaded = request.getFile(itr.next());
    raf.write(fileUploaded.getBytes());
}

raf.close();

I had to do more fixes to the java code provided because it was estimating the number of chunks to receive wrong, so I just used the "flowTotalChunks" parameter.

otterslide
  • 550
  • 6
  • 14
0

You don't need to worry about content length. The HttpServletRequest will terminate the input stream at the correct point. Just read until end of stream.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • if try "while ((read = uploadedInputStream.read(bytes)) != -1)" the result is the same, the first reading is -1 so upload 0 bytes. – Jose Antonio Feb 25 '16 at 22:56
  • Then nothing was sent. – user207421 Feb 25 '16 at 22:59
  • I know it but I want to know why the file is not sent with Flowjs and how fix it. I found this: http://stackoverflow.com/questions/25740110/flow-js-upload-file-on-click?rq=1 but the result is the same, the file is not sent. – Jose Antonio Feb 26 '16 at 20:38
  • Have you tried a different browser? after checking mine, it does receive data, but there are other problems you will run into even when you receive some input because the Java code isn't completely up to date with the Javascript side. – otterslide Apr 05 '16 at 01:49
0

I wanted a lib to upload images with more options and visually appealing (drop file from a folder, thumbnail, etc) than the default html input and I have not been able to do with Flowjs and Java Servlet, so I looked for another lib:

https://github.com/danialfarid/ng-file-upload

https://angular-file-upload.appspot.com/

With this lib, I found it easy to use with Java Servlet.

I don't mark this post as solved for if someone finds a way to do it with Flowjs.

Jose Antonio
  • 578
  • 1
  • 8
  • 34
  • I thought flow.js is working very well with angular, so I also attempted to use and got the same problem as you did. The problem seems to be in the Java code, it seems to be out of date and does not look at currentChunkSize, and ends up thinking it didn't receive all the chunks. I will try to fix it and let you know. – otterslide Apr 04 '16 at 20:53
  • @user1384975 I found the other lib that I said and it works fine so I forgot Flowjs although Flowjs is a bit more complete. If you find the solution with Flowjs, let me know please. – Jose Antonio Apr 06 '16 at 09:35
  • solution found, I've posted it. You need to set upload type of octet, or handle multi-part post if not. – otterslide Apr 09 '16 at 17:09