Файл Flow.js и сервлет Java загружают 0 байтов

Я добавил flow.js в свой проект, следуя инструкциям и вызову моего Java-сервлета:

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

В моем сервлете я получаю все параметры URL (flowChuckNumber, flowChuckSize и т. Д.), Но когда я пытаюсь получить файл (request.getInputStream()), он пуст и загружает 0 байт.

В чем проблема? Любая идея?

Я нашел похожий вопрос, но это было с PHP...

Мой код:

HTML (изображение отображается):

...
...
<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>
...
...

Приложение 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;
    });

Мой сервлет (я последовал этому примеру):

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();
...
...

3 ответа

Решение

Входной поток будет пустым, потому что flowjs публикует контент, используя MultiPart по умолчанию. Автор Java-кода указал, что "Octet" должен использоваться для загрузки, а не для нескольких частей.

UploadServlet принимает Resumable.js Загрузить с помощью 'octet'

Вам нужно добавить "method:octet" в ваш init,

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

Я использую Spring, поэтому я просто использовал MultipartHttpServletRequest для получения опубликованных данных с MultiPart, потому что MultiPart является более распространенным.

Вот как я получил содержимое файла:

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();

Мне пришлось сделать больше исправлений к предоставленному Java-коду, потому что он оценивал количество порций для получения неправильных, поэтому я просто использовал параметр "flowTotalChunks".

Вам не нужно беспокоиться о длине контента. HttpServletRequest завершит входной поток в правильной точке. Просто прочитайте до конца потока.

Я хотел, чтобы библиотека загружала изображения с большим количеством опций и визуально привлекательнее (перетаскивать файл из папки, миниатюры и т. Д.), Чем ввод по умолчанию в формате html, и у меня не было возможности работать с Flowjs и сервлетом Java, поэтому я искал другую библиотеку:

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

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

С этой библиотекой я обнаружил, что ее легко использовать с сервлетом Java.

Я не отмечаю этот пост как решенный, если кто-то найдет способ сделать это с помощью Flowjs.

Другие вопросы по тегам