mirror of https://github.com/apache/poi.git
[bug-65042] support saving package part data in temp files
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1894203 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5b7b8ae1a9
commit
defd26493f
|
@ -518,7 +518,7 @@ public abstract class PackagePart implements RelationshipSource, Comparable<Pack
|
|||
* @return output stream for this part
|
||||
* @see org.apache.poi.openxml4j.opc.internal.MemoryPackagePart
|
||||
*/
|
||||
public OutputStream getOutputStream() {
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
OutputStream outStream;
|
||||
// If this part is a zip package part (read only by design) we convert
|
||||
// this part into a MemoryPackagePart instance for write purpose.
|
||||
|
@ -674,9 +674,8 @@ public abstract class PackagePart implements RelationshipSource, Comparable<Pack
|
|||
* Method that gets the input stream for this part.
|
||||
*
|
||||
* @return input stream for this part
|
||||
* @exception IOException
|
||||
* Throws if an IO Exception occur in the implementation
|
||||
* method.
|
||||
* @throws IOException
|
||||
* Throws if an IO Exception occur in the implementation method.
|
||||
*/
|
||||
protected abstract InputStream getInputStreamImpl() throws IOException;
|
||||
|
||||
|
@ -684,8 +683,10 @@ public abstract class PackagePart implements RelationshipSource, Comparable<Pack
|
|||
* Method that gets the output stream for this part.
|
||||
*
|
||||
* @return output stream for this part
|
||||
* @throws IOException
|
||||
* Throws if an IO Exception occur in the implementation method.
|
||||
*/
|
||||
protected abstract OutputStream getOutputStreamImpl();
|
||||
protected abstract OutputStream getOutputStreamImpl() throws IOException;
|
||||
|
||||
/**
|
||||
* Save the content of this part and the associated relationships part (if
|
||||
|
|
|
@ -43,12 +43,7 @@ import org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException;
|
|||
import org.apache.poi.openxml4j.exceptions.ODFNotOfficeXmlFileException;
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
|
||||
import org.apache.poi.openxml4j.opc.internal.ContentTypeManager;
|
||||
import org.apache.poi.openxml4j.opc.internal.FileHelper;
|
||||
import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart;
|
||||
import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
|
||||
import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager;
|
||||
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
|
||||
import org.apache.poi.openxml4j.opc.internal.*;
|
||||
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
|
||||
import org.apache.poi.openxml4j.util.ZipArchiveThresholdInputStream;
|
||||
import org.apache.poi.openxml4j.util.ZipEntrySource;
|
||||
|
@ -63,6 +58,8 @@ import org.apache.poi.util.TempFile;
|
|||
public final class ZipPackage extends OPCPackage {
|
||||
private static final String MIMETYPE = "mimetype";
|
||||
private static final String SETTINGS_XML = "settings.xml";
|
||||
private static boolean useTempFilePackageParts = false;
|
||||
private static boolean encryptTempFilePackageParts = false;
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(ZipPackage.class);
|
||||
|
||||
|
@ -72,6 +69,34 @@ public final class ZipPackage extends OPCPackage {
|
|||
*/
|
||||
private final ZipEntrySource zipArchive;
|
||||
|
||||
/**
|
||||
* @param tempFilePackageParts whether to save package part data in temp files to save memory
|
||||
*/
|
||||
public void setUseTempFilePackageParts(boolean tempFilePackageParts) {
|
||||
useTempFilePackageParts = tempFilePackageParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param encryptTempFiles whether to encrypt temp files
|
||||
*/
|
||||
public void setEncryptTempFilePackageParts(boolean encryptTempFiles) {
|
||||
encryptTempFilePackageParts = encryptTempFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether package part data is stored in temp files to save memory
|
||||
*/
|
||||
public boolean useTempFilePackageParts() {
|
||||
return useTempFilePackageParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether package part temp files are encrypted
|
||||
*/
|
||||
public boolean encryptTempFilePackageParts() {
|
||||
return encryptTempFilePackageParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Creates a new, empty ZipPackage.
|
||||
*/
|
||||
|
@ -371,8 +396,16 @@ public final class ZipPackage extends OPCPackage {
|
|||
}
|
||||
|
||||
try {
|
||||
return new MemoryPackagePart(this, partName, contentType, loadRelationships);
|
||||
} catch (InvalidFormatException e) {
|
||||
if (useTempFilePackageParts) {
|
||||
if (encryptTempFilePackageParts) {
|
||||
return new EncryptedTempFilePackagePart(this, partName, contentType, loadRelationships);
|
||||
} else {
|
||||
return new TempFilePackagePart(this, partName, contentType, loadRelationships);
|
||||
}
|
||||
} else {
|
||||
return new MemoryPackagePart(this, partName, contentType, loadRelationships);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.atWarn().withThrowable(e).log("Failed to create part {}", partName);
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public class ZipPackagePart extends PackagePart {
|
|||
/**
|
||||
* Get the zip entry of this part.
|
||||
*
|
||||
* @return The zip entry in the zip structure coresponding to this part.
|
||||
* @return The zip entry in the zip structure corresponding to this part.
|
||||
*/
|
||||
public ZipArchiveEntry getZipArchive() {
|
||||
return zipEntry;
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.openxml4j.opc.internal;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackagePartName;
|
||||
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
|
||||
import org.apache.poi.poifs.crypt.temp.EncryptedTempData;
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.TempFile;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* (Experimental) Encrypted Temp File version of a package part.
|
||||
*
|
||||
* @since POI 5.1.0
|
||||
*/
|
||||
@Beta
|
||||
public final class EncryptedTempFilePackagePart extends PackagePart {
|
||||
private static final Logger LOG = LogManager.getLogger(EncryptedTempFilePackagePart.class);
|
||||
|
||||
/**
|
||||
* Storage for the part data.
|
||||
*/
|
||||
private EncryptedTempData tempFile;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param pack
|
||||
* The owner package.
|
||||
* @param partName
|
||||
* The part name.
|
||||
* @param contentType
|
||||
* The content type.
|
||||
* @throws InvalidFormatException
|
||||
* If the specified URI is not OPC compliant.
|
||||
* @throws IOException
|
||||
* If temp file cannot be created.
|
||||
*/
|
||||
public EncryptedTempFilePackagePart(OPCPackage pack, PackagePartName partName,
|
||||
String contentType) throws InvalidFormatException, IOException {
|
||||
this(pack, partName, contentType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param pack
|
||||
* The owner package.
|
||||
* @param partName
|
||||
* The part name.
|
||||
* @param contentType
|
||||
* The content type.
|
||||
* @param loadRelationships
|
||||
* Specify if the relationships will be loaded.
|
||||
* @throws InvalidFormatException
|
||||
* If the specified URI is not OPC compliant.
|
||||
* @throws IOException
|
||||
* If temp file cannot be created.
|
||||
*/
|
||||
public EncryptedTempFilePackagePart(OPCPackage pack, PackagePartName partName,
|
||||
String contentType, boolean loadRelationships)
|
||||
throws InvalidFormatException, IOException {
|
||||
super(pack, partName, new ContentType(contentType), loadRelationships);
|
||||
tempFile = new EncryptedTempData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getInputStreamImpl() throws IOException {
|
||||
return tempFile.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getOutputStreamImpl() throws IOException {
|
||||
return tempFile.getOutputStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EncryptedTempData.getSize() always returns -1
|
||||
*/
|
||||
@Override
|
||||
public long getSize() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
try(OutputStream os = getOutputStreamImpl()) {
|
||||
os.write(new byte[0]);
|
||||
} catch (IOException e) {
|
||||
LOG.atWarn().log("Failed to clear data in temp file", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save(OutputStream os) throws OpenXML4JException {
|
||||
return new ZipPartMarshaller().marshall(this, os);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean load(InputStream ios) throws InvalidFormatException {
|
||||
try (OutputStream os = getOutputStreamImpl()) {
|
||||
IOUtils.copy(ios, os);
|
||||
} catch(IOException e) {
|
||||
throw new InvalidFormatException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
// All done
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
tempFile.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
|
@ -113,17 +113,17 @@ public final class MemoryPackagePart extends PackagePart {
|
|||
|
||||
@Override
|
||||
public boolean load(InputStream ios) throws InvalidFormatException {
|
||||
try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) {
|
||||
// Grab the data
|
||||
IOUtils.copy(ios, baos);
|
||||
// Save it
|
||||
data = baos.toByteArray();
|
||||
} catch(IOException e) {
|
||||
throw new InvalidFormatException(e.getMessage());
|
||||
}
|
||||
try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) {
|
||||
// Grab the data
|
||||
IOUtils.copy(ios, baos);
|
||||
// Save it
|
||||
data = baos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
throw new InvalidFormatException(e.getMessage());
|
||||
}
|
||||
|
||||
// All done
|
||||
return true;
|
||||
// All done
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.openxml4j.opc.internal;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackagePartName;
|
||||
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.TempFile;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* (Experimental) Temp File version of a package part.
|
||||
*
|
||||
* @since POI 5.1.0
|
||||
*/
|
||||
@Beta
|
||||
public final class TempFilePackagePart extends PackagePart {
|
||||
private static final Logger LOG = LogManager.getLogger(TempFilePackagePart.class);
|
||||
|
||||
/**
|
||||
* Storage for the part data.
|
||||
*/
|
||||
private File tempFile;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param pack
|
||||
* The owner package.
|
||||
* @param partName
|
||||
* The part name.
|
||||
* @param contentType
|
||||
* The content type.
|
||||
* @throws InvalidFormatException
|
||||
* If the specified URI is not OPC compliant.
|
||||
* @throws IOException
|
||||
* If temp file cannot be created.
|
||||
*/
|
||||
public TempFilePackagePart(OPCPackage pack, PackagePartName partName,
|
||||
String contentType) throws InvalidFormatException, IOException {
|
||||
this(pack, partName, contentType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param pack
|
||||
* The owner package.
|
||||
* @param partName
|
||||
* The part name.
|
||||
* @param contentType
|
||||
* The content type.
|
||||
* @param loadRelationships
|
||||
* Specify if the relationships will be loaded.
|
||||
* @throws InvalidFormatException
|
||||
* If the specified URI is not OPC compliant.
|
||||
* @throws IOException
|
||||
* If temp file cannot be created.
|
||||
*/
|
||||
public TempFilePackagePart(OPCPackage pack, PackagePartName partName,
|
||||
String contentType, boolean loadRelationships)
|
||||
throws InvalidFormatException, IOException {
|
||||
super(pack, partName, new ContentType(contentType), loadRelationships);
|
||||
tempFile = TempFile.createTempFile("poi-package-part", ".tmp");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getInputStreamImpl() throws IOException {
|
||||
return new FileInputStream(tempFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getOutputStreamImpl() throws IOException {
|
||||
return new FileOutputStream(tempFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return tempFile.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
try(OutputStream os = getOutputStreamImpl()) {
|
||||
os.write(new byte[0]);
|
||||
} catch (IOException e) {
|
||||
LOG.atWarn().log("Failed to clear data in temp file", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save(OutputStream os) throws OpenXML4JException {
|
||||
return new ZipPartMarshaller().marshall(this, os);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean load(InputStream ios) throws InvalidFormatException {
|
||||
try (OutputStream os = getOutputStreamImpl()) {
|
||||
IOUtils.copy(ios, os);
|
||||
} catch(IOException e) {
|
||||
throw new InvalidFormatException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
// All done
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (!tempFile.delete()) {
|
||||
LOG.atInfo().log("Failed to delete temp file; may already have been closed and deleted");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
|
@ -57,7 +57,7 @@ public class XSLFFontData extends POIXMLDocumentPart {
|
|||
return getPackagePart().getInputStream();
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
final PackagePart pp = getPackagePart();
|
||||
pp.clear();
|
||||
return pp.getOutputStream();
|
||||
|
|
|
@ -59,7 +59,7 @@ public final class XSLFObjectData extends POIXMLDocumentPart implements ObjectDa
|
|||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
final PackagePart pp = getPackagePart();
|
||||
pp.clear();
|
||||
return pp.getOutputStream();
|
||||
|
|
Loading…
Reference in New Issue