2

私はdocuments4jを使用してWord文書をPDFに変換していますが、例外が発生することがあります

2016-03-28 09:29:16.982  INFO 3660 --- [pool-1-thread-2] c.d.c.msoffice.MicrosoftWordBridge       : Requested conversion from C:\conversion-temp\2b33637b-b74a-4aaa-ac65-a5ebc1eb3efc\temp3 (application/msword) to C:\conversion-temp\2b33637b-b74a-4aaa-ac65-a5ebc1eb3efc\temp4 (application/pdf)
2016-03-28 09:29:17.372 ERROR 3660 --- [http-nio-8080-exec-9] c.s.c.e.mappers.ExceptionMapper          : Exception while handling request

com.documents4j.throwables.FileSystemInteractionException: Could not access target file
  at com.documents4j.util.Reaction$FileSystemInteractionExceptionBuilder.make(Reaction.java:180) ~[documents4j-util-all-1.0.2.jar:na]
  at com.documents4j.util.Reaction$ExceptionalReaction.apply(Reaction.java:75) ~[documents4j-util-all-1.0.2.jar:na]
  at com.documents4j.conversion.ExternalConverterScriptResult.resolve(ExternalConverterScriptResult.java:70) ~[documents4j-transformer-api-1.0.2.jar:na]
  at com.documents4j.conversion.ProcessFutureWrapper.evaluateExitValue(ProcessFutureWrapper.java:48) ~[documents4j-util-transformer-process-1.0.2.jar:na]
  at com.documents4j.conversion.ProcessFutureWrapper.get(ProcessFutureWrapper.java:36) ~[documents4j-util-transformer-process-1.0.2.jar:na]
  at com.documents4j.conversion.ProcessFutureWrapper.get(ProcessFutureWrapper.java:11) ~[documents4j-util-transformer-process-1.0.2.jar:na]
  at com.documents4j.job.AbstractFutureWrappingPriorityFuture.run(AbstractFutureWrappingPriorityFuture.java:78) ~[documents4j-util-conversion-1.0.2.jar:na]
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_74]
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_74]
  at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_74]

この例外の後、次の例外を除いて、以降のリクエストはすべて documents4j ライブラリによって拒否されます

com.documents4j.throwables.ConverterAccessException: The converter seems to be shut down
  at com.documents4j.util.Reaction$ConverterAccessExceptionBuilder.make(Reaction.java:117) ~[documents4j-util-all-1.0.2.jar:na]
  at com.documents4j.util.Reaction$ExceptionalReaction.apply(Reaction.java:75) ~[documents4j-util-all-1.0.2.jar:na]
  at com.documents4j.conversion.ExternalConverterScriptResult.resolve(ExternalConverterScriptResult.java:70) ~[documents4j-transformer-api-1.0.2.jar:na]
  at com.documents4j.conversion.ProcessFutureWrapper.evaluateExitValue(ProcessFutureWrapper.java:48) ~[documents4j-util-transformer-process-1.0.2.jar:na]
  at com.documents4j.conversion.ProcessFutureWrapper.get(ProcessFutureWrapper.java:36) ~[documents4j-util-transformer-process-1.0.2.jar:na]
  at com.documents4j.conversion.ProcessFutureWrapper.get(ProcessFutureWrapper.java:11) ~[documents4j-util-transformer-process-1.0.2.jar:na]
  at com.documents4j.job.AbstractFutureWrappingPriorityFuture.run(AbstractFutureWrappingPriorityFuture.java:78) ~[documents4j-util-conversion-1.0.2.jar:na]
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_74]
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_74]
  at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_74]

これは、ドキュメントの変換を行う方法です。

LocalConverter のインスタンスをインスタンス化しています

LocalConverter.builder().workerPool(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES).baseFolder(baseFolder).processTimeout(processTimeout, TimeUnit.SECONDS).build();

corePoolSize is 5
maximumPoolSize is 10
keepAliveTime is 3 minutes
processTimeout is 20 minutes

そして、私はこのインスタンスを次のように使用しています

public File convertFile(MultipartFile file) throws ConversionException {
        try(InputStream docStream = file.getInputStream(); ByteArrayOutputStream pdfStream = new ByteArrayOutputStream()) {
            boolean status = iConverter.convert(docStream, false).as(DocumentType.DOC).to(pdfStream, false).as(DocumentType.PDF).execute();
            if(status) {
                // conversion is success, send the response
                File response = new File();
                //InputStream responseStream = new ByteArrayInputStream(pdfStream.toByteArray());
                response.setContentLength(pdfStream.size());
                //response.setInputStream(responseStream);
                response.setOutputStream(pdfStream);
                return response;
            } else {
                LOGGER.error("Failed to convert word to pdf, conversion status is {}", status);
                throw new ConversionException("failed to convert word to pdf");
            }
        } catch (FileSystemInteractionException fsie) {
            LOGGER.error("documents4j file system interaction exception", fsie);
            throw new ConversionException("File system exception", fsie);
        } catch(IOException ioe) {
            throw new ConversionException("Cannot read the input stream of file", ioe);
        }
    }

このマルチパート ファイルは、Spring マルチパート ファイルです。documents4j が変換に使用する vb スクリプトを確認したところ、wordDocument が適切に閉じられていない場合にこのエラーが発生することがわかりました。以下は、このエラーの原因である vb スクリプトのスニペットです。

' Close the source document.
wordDocument.Close WdDoNotSaveChanges
If Err <> 0 Then
    WScript.Quit -3
End If
On Error GoTo 0

なぜ私が得ているのか分かりませんFileSystemInteractionException

私が考えることができる2つの仮定があります

  1. 複数の同時リクエストを送信していますが、ファイルは他のスレッドによって削除されています
  2. MultipartFile オブジェクトから入力ストリームを取得していますが、マルチパート ファイルは一時的なものであり、ドキュメントに従って、ユーザーはコンテンツを永続的なストレージにコピーする責任があります。

春の公式ドキュメント

このエラーを解決するにはどうすればよいですか。また、このエラーの根本的な原因は何ですか。

4

2 に答える 2

1

このエラーには複数の理由が考えられます。

com.documents4j.throwables.FileSystemInteractionException: Could not access target file

例外のドキュメントはこちら

アップロードされたマルチパート ファイルを一時ファイルに保存してから、この一時ファイルをコンバーターに渡してみましたか? これが不要なオーバーヘッドであることは承知しています。ただし、これが機能する場合は、IConverter インスタンスがアクセスしようとしたときに入力「docstream」が完全に入力されていないため、エラーが発生したと安全に想定できます。この場合、変換を試みる前に入力ストリームが設定されていることを確認する必要があります。これにより、問題が解決するはずです。

「ファイルベース」の変換シナリオでもこのエラーが発生する場合は、次の手順を試してください。

  1. MS Office アプリケーションが実行されていないことを確認します (Word 文書を外部で開いたため)。
  2. (JVM だけでなく) 物理マシン全体で実行されている IConverter のインスタンスが 1 つだけ存在することを確認します。
  3. Tomcat をサービスとして実行している場合 (これを Tomcat にデプロイしていると想定しています)、Tomcat を SYSTEM アカウント サービスとしてではなく、ローカル ユーザー アカウントとして実行しています。
  4. Web アプリケーションでは、(シングルトン クラスのように) IConverter インスタンスを 1 回作成する必要があり、ビジネス メソッドの 1 つによって要求されるたびに同じインスタンスを返す必要があります。また、ドキュメント変換要求が同時に発生することが予想される場合は、コンバータをシャットダウンしないでください。

理想的には、これらの手順のいずれかで問題を解決する必要があります。まだこの問題に直面している場合は、コメントでお知らせください。

于 2016-05-05T20:36:37.123 に答える