Abstraction for storing binary asset data, and default implementation using java.sql.Blob and Streams.
parent
31015b0739
commit
c8382b6660
|
|
@ -96,7 +96,8 @@ import java.util.Properties;
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
configurations = {
|
configurations = {
|
||||||
org.librecms.CMSConfig.class
|
org.librecms.CMSConfig.class,
|
||||||
|
org.librecms.assets.BinaryAssetConfig.class
|
||||||
},
|
},
|
||||||
pageModelComponentModels = {
|
pageModelComponentModels = {
|
||||||
@PageModelComponentModel(
|
@PageModelComponentModel(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.assets;
|
||||||
|
|
||||||
|
import org.libreccm.core.UnexpectedErrorException;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.sql.Blob;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.enterprise.context.Dependent;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@Dependent
|
||||||
|
public class BinaryAssetBlobDataProvider implements BinaryAssetDataProvider {
|
||||||
|
|
||||||
|
@Resource(lookup = "java:/comp/env/jdbc/libreccm/db")
|
||||||
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream retrieveData(final BinaryAsset asset) {
|
||||||
|
Objects.requireNonNull(asset, "Can't retrieve data from null.");
|
||||||
|
try ( Connection connection = dataSource.getConnection()) {
|
||||||
|
final PreparedStatement stmt = connection
|
||||||
|
.prepareStatement(
|
||||||
|
"SELECT data FROM binary_assets WHERE object_id = ?"
|
||||||
|
);
|
||||||
|
stmt.setLong(1, asset.getObjectId());
|
||||||
|
|
||||||
|
try (ResultSet resultSet = stmt.executeQuery()) {
|
||||||
|
final Blob blob = resultSet.getBlob("data");
|
||||||
|
return blob.getBinaryStream();
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
throw new UnexpectedErrorException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveData(final BinaryAsset asset, final InputStream stream) {
|
||||||
|
Objects.requireNonNull(asset, "Can't save data to null.");
|
||||||
|
try ( Connection connection = dataSource.getConnection()) {
|
||||||
|
final PreparedStatement stmt = connection
|
||||||
|
.prepareStatement(
|
||||||
|
"UPDATE binary_assets SET data = ? WHERE object_id = ?"
|
||||||
|
);
|
||||||
|
stmt.setBlob(1, stream);
|
||||||
|
stmt.setLong(2, asset.getObjectId());
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
throw new UnexpectedErrorException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.assets;
|
||||||
|
|
||||||
|
import org.libreccm.configuration.Configuration;
|
||||||
|
import org.libreccm.configuration.Setting;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration parameters for binary assets.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public final class BinaryAssetConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the implementation of {@link BinaryAssetDataProvider} to use.
|
||||||
|
*/
|
||||||
|
@Setting
|
||||||
|
private String binaryAssetDataProvider = BinaryAssetBlobDataProvider.class
|
||||||
|
.getName();
|
||||||
|
|
||||||
|
public String getBinaryAssetDataProvider() {
|
||||||
|
return binaryAssetDataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBinaryAssetDataProvider(final String binaryAssetDataProvider) {
|
||||||
|
this.binaryAssetDataProvider = binaryAssetDataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 3;
|
||||||
|
hash = 67 * hash + Objects.hashCode(binaryAssetDataProvider);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(obj instanceof BinaryAssetConfig)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final BinaryAssetConfig other = (BinaryAssetConfig) obj;
|
||||||
|
return Objects.equals(
|
||||||
|
binaryAssetDataProvider,
|
||||||
|
other.binaryAssetDataProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format(
|
||||||
|
"%s{ "
|
||||||
|
+ "binaryAssetDataProvider = %s"
|
||||||
|
+ " }",
|
||||||
|
binaryAssetDataProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.assets;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public interface BinaryAssetDataProvider {
|
||||||
|
|
||||||
|
InputStream retrieveData(BinaryAsset asset);
|
||||||
|
|
||||||
|
void saveData(BinaryAsset asset, InputStream stream);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.assets;
|
||||||
|
|
||||||
|
import org.libreccm.configuration.ConfigurationManager;
|
||||||
|
import org.libreccm.core.UnexpectedErrorException;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.enterprise.inject.Any;
|
||||||
|
import javax.enterprise.inject.Instance;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
public class BinaryAssetDataService {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ConfigurationManager confManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Any
|
||||||
|
private Instance<BinaryAssetDataProvider> dataProvider;
|
||||||
|
|
||||||
|
public InputStream retrieveData(final BinaryAsset asset) {
|
||||||
|
Objects.requireNonNull(asset, "Can't retrieve data from null.");
|
||||||
|
|
||||||
|
final BinaryAssetDataProvider dataProvider = getDataProvider();
|
||||||
|
|
||||||
|
return dataProvider.retrieveData(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveData(final BinaryAsset asset, final InputStream stream) {
|
||||||
|
Objects.requireNonNull(asset, "Can't save data to null.");
|
||||||
|
|
||||||
|
final BinaryAssetDataProvider dataProvider = getDataProvider();
|
||||||
|
dataProvider.saveData(asset, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private BinaryAssetDataProvider getDataProvider() {
|
||||||
|
final BinaryAssetConfig config = confManager.findConfiguration(
|
||||||
|
BinaryAssetConfig.class
|
||||||
|
);
|
||||||
|
|
||||||
|
final Class<? extends BinaryAssetDataProvider> clazz;
|
||||||
|
try {
|
||||||
|
clazz = (Class<? extends BinaryAssetDataProvider>) Class.forName(
|
||||||
|
config.getBinaryAssetDataProvider()
|
||||||
|
);
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new UnexpectedErrorException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Instance<? extends BinaryAssetDataProvider> selectedInstance
|
||||||
|
= dataProvider.select(clazz);
|
||||||
|
|
||||||
|
if (selectedInstance.isResolvable()) {
|
||||||
|
return selectedInstance.get();
|
||||||
|
} else {
|
||||||
|
throw new UnexpectedErrorException(
|
||||||
|
String.format(
|
||||||
|
"The configured implementation of %s could not be resolved.",
|
||||||
|
BinaryAssetDataProvider.class.getName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -319,7 +319,6 @@ public class Images {
|
||||||
LOGGER.error(ex);
|
LOGGER.error(ex);
|
||||||
return Response.serverError().build();
|
return Response.serverError().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response
|
return Response
|
||||||
.ok(outputStream.toByteArray(), mimeType)
|
.ok(outputStream.toByteArray(), mimeType)
|
||||||
.build();
|
.build();
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ public class CmsAssetEditSteps implements MvcAssetEditSteps {
|
||||||
public Set<Class<?>> getResourceClasses() {
|
public Set<Class<?>> getResourceClasses() {
|
||||||
final Set<Class<?>> classes = new HashSet<>();
|
final Set<Class<?>> classes = new HashSet<>();
|
||||||
|
|
||||||
|
classes.add(FileAssetEditStepDownload.class);
|
||||||
classes.add(SideNoteEditStepResources.class);
|
classes.add(SideNoteEditStepResources.class);
|
||||||
|
|
||||||
return classes;
|
return classes;
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,12 @@ import org.jboss.resteasy.plugins.providers.multipart.InputPart;
|
||||||
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
|
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
import org.libreccm.l10n.GlobalizationHelper;
|
||||||
import org.libreccm.security.AuthorizationRequired;
|
import org.libreccm.security.AuthorizationRequired;
|
||||||
|
import org.librecms.assets.BinaryAssetDataService;
|
||||||
import org.librecms.assets.FileAsset;
|
import org.librecms.assets.FileAsset;
|
||||||
import org.librecms.contentsection.AssetRepository;
|
import org.librecms.contentsection.AssetRepository;
|
||||||
import org.librecms.ui.contentsections.AssetPermissionsChecker;
|
import org.librecms.ui.contentsections.AssetPermissionsChecker;
|
||||||
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
|
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -55,6 +55,7 @@ import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -84,6 +85,9 @@ public class FileAssetEditStep extends AbstractMvcAssetEditStep {
|
||||||
@Inject
|
@Inject
|
||||||
private AssetRepository assetRepo;
|
private AssetRepository assetRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BinaryAssetDataService dataService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private GlobalizationHelper globalizationHelper;
|
private GlobalizationHelper globalizationHelper;
|
||||||
|
|
||||||
|
|
@ -312,6 +316,9 @@ public class FileAssetEditStep extends AbstractMvcAssetEditStep {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("/upload")
|
@Path("/upload")
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
|
@ -348,19 +355,10 @@ public class FileAssetEditStep extends AbstractMvcAssetEditStep {
|
||||||
.getHeaders();
|
.getHeaders();
|
||||||
fileName = getFileName(headers);
|
fileName = getFileName(headers);
|
||||||
contentType = getContentType(headers);
|
contentType = getContentType(headers);
|
||||||
final byte[] bytes = new byte[1024];
|
dataService.saveData(
|
||||||
try (InputStream inputStream = inputPart.getBody(
|
fileAsset,
|
||||||
InputStream.class, null
|
inputPart.getBody(InputStream.class, null)
|
||||||
);
|
);
|
||||||
ByteArrayOutputStream fileDataOutputStream
|
|
||||||
= new ByteArrayOutputStream()) {
|
|
||||||
while (inputStream.read(bytes) != -1) {
|
|
||||||
fileDataOutputStream.writeBytes(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
fileAsset.setData(fileDataOutputStream.toByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.error(
|
LOGGER.error(
|
||||||
"Failed to upload file for FileAsset {}:", assetPath
|
"Failed to upload file for FileAsset {}:", assetPath
|
||||||
|
|
@ -370,6 +368,33 @@ public class FileAssetEditStep extends AbstractMvcAssetEditStep {
|
||||||
models.put("uploadFailed", true);
|
models.put("uploadFailed", true);
|
||||||
return buildRedirectPathForStep();
|
return buildRedirectPathForStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// final MultivaluedMap<String, String> headers = inputPart
|
||||||
|
// .getHeaders();
|
||||||
|
// fileName = getFileName(headers);
|
||||||
|
// contentType = getContentType(headers);
|
||||||
|
// final byte[] bytes = new byte[1024];
|
||||||
|
// try (InputStream inputStream = inputPart.getBody(
|
||||||
|
// InputStream.class, null
|
||||||
|
// );
|
||||||
|
// ByteArrayOutputStream fileDataOutputStream
|
||||||
|
// = new ByteArrayOutputStream()) {
|
||||||
|
// while (inputStream.read(bytes) != -1) {
|
||||||
|
// fileDataOutputStream.writeBytes(bytes);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fileAsset.setData(fileDataOutputStream.toByteArray());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } catch (IOException ex) {
|
||||||
|
// LOGGER.error(
|
||||||
|
// "Failed to upload file for FileAsset {}:", assetPath
|
||||||
|
// );
|
||||||
|
// LOGGER.error(ex);
|
||||||
|
//
|
||||||
|
// models.put("uploadFailed", true);
|
||||||
|
// return buildRedirectPathForStep();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fileAsset.setFileName(fileName);
|
fileAsset.setFileName(fileName);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections.assets;
|
||||||
|
|
||||||
|
import org.libreccm.security.AuthorizationRequired;
|
||||||
|
import org.librecms.assets.BinaryAssetDataService;
|
||||||
|
import org.librecms.assets.FileAsset;
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
import org.librecms.contentsection.AssetRepository;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
|
||||||
|
import org.librecms.ui.contentsections.ContentSectionsUi;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.mail.internet.ContentDisposition;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.StreamingOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
@Path(MvcAssetEditSteps.PATH_PREFIX + "fileasset-edit-download")
|
||||||
|
|
||||||
|
public class FileAssetEditStepDownload {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssetRepository assetRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BinaryAssetDataService dataService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ContentSectionsUi sectionsUi;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public Response downloadFile(
|
||||||
|
@PathParam(MvcAssetEditSteps.SECTION_IDENTIFIER_PATH_PARAM)
|
||||||
|
final String sectionIdentifier,
|
||||||
|
@PathParam(MvcAssetEditSteps.ASSET_PATH_PATH_PARAM_NAME)
|
||||||
|
final String assetPath
|
||||||
|
) {
|
||||||
|
|
||||||
|
final ContentSection contentSection = sectionsUi
|
||||||
|
.findContentSection(sectionIdentifier)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new WebApplicationException(
|
||||||
|
Response
|
||||||
|
.status(Response.Status.NOT_FOUND)
|
||||||
|
.entity(
|
||||||
|
String.format(
|
||||||
|
"ContentSection %s not found.",
|
||||||
|
sectionIdentifier
|
||||||
|
)
|
||||||
|
).build()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
final Asset asset = assetRepo
|
||||||
|
.findByPath(contentSection, assetPath)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new WebApplicationException(
|
||||||
|
Response
|
||||||
|
.status(Response.Status.NOT_FOUND)
|
||||||
|
.entity(
|
||||||
|
String.format(
|
||||||
|
"No asset for path %s found in section %s.",
|
||||||
|
assetPath,
|
||||||
|
contentSection.getLabel()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!(asset instanceof FileAsset)) {
|
||||||
|
throw new WebApplicationException(
|
||||||
|
Response
|
||||||
|
.status(Response.Status.NOT_FOUND)
|
||||||
|
.entity(
|
||||||
|
String.format(
|
||||||
|
"No asset for path %s found in section %s.",
|
||||||
|
assetPath,
|
||||||
|
contentSection.getLabel()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final FileAsset fileAsset = (FileAsset) asset;
|
||||||
|
try ( InputStream dataInputStream = dataService.retrieveData(fileAsset)) {
|
||||||
|
|
||||||
|
final StreamingOutput output = new StreamingOutput() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(final OutputStream outputStream)
|
||||||
|
throws IOException, WebApplicationException {
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int length;
|
||||||
|
while ((length = dataInputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return Response
|
||||||
|
.ok()
|
||||||
|
.entity(output)
|
||||||
|
.header("Content-Type", fileAsset.getMimeType())
|
||||||
|
.header(
|
||||||
|
"Content-Disposition",
|
||||||
|
String.format(
|
||||||
|
"attachment; filename=\"%s\"",
|
||||||
|
fileAsset.getFileName()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new WebApplicationException(
|
||||||
|
ex,
|
||||||
|
Response.Status.INTERNAL_SERVER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// private class FileAssetOutput implements StreamingOutput {
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void write(final OutputStream outputStream)
|
||||||
|
// throws IOException, WebApplicationException {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
@ -52,14 +52,19 @@
|
||||||
|
|
||||||
<h3>#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.title']}</h3>
|
<h3>#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.title']}</h3>
|
||||||
<c:if test="#{MvcAssetEditStepModel.canEdit}">
|
<c:if test="#{MvcAssetEditStepModel.canEdit}">
|
||||||
<div class="text-right">
|
<div class="text-left">
|
||||||
<button class="btn btn-primary"
|
<button class="btn btn-primary"
|
||||||
data-toggle="modal"
|
data-toggle="modal"
|
||||||
data-target="#file-upload-dialog"
|
data-target="#file-upload-dialog"
|
||||||
type="button">
|
type="button">
|
||||||
<bootstrap:svgIcon icon="upload" />
|
<bootstrap:svgIcon icon="upload" />
|
||||||
<span class="sr-only">#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.upload.button.label']}</span>
|
<span>#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.upload.button.label']}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<a class="btn btn-primary"
|
||||||
|
href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/assets/#{CmsSelectedAssetModel.assetPath}/@fileasset-edit-download">
|
||||||
|
<bootstrap:svgIcon icon="download" />
|
||||||
|
<span>#{CmsAssetsStepsDefaultMessagesBundle['fileasset.editstep.file.download.button.label']}</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div aria-hidden="true"
|
<div aria-hidden="true"
|
||||||
aria-labelledby="file-upload-dialog-title"
|
aria-labelledby="file-upload-dialog-title"
|
||||||
|
|
|
||||||
|
|
@ -387,3 +387,4 @@ createform.externalvideoasset.url.help=The URL of the external video. The video
|
||||||
createform.externalvideoasset.url.label=URL
|
createform.externalvideoasset.url.label=URL
|
||||||
createform.externalvideoasset.description.help=A short description of the contents of the video.
|
createform.externalvideoasset.description.help=A short description of the contents of the video.
|
||||||
createform.externalvideoasset.description.label=Description
|
createform.externalvideoasset.description.label=Description
|
||||||
|
fileasset.editstep.file.download.button.label=Download File
|
||||||
|
|
|
||||||
|
|
@ -387,3 +387,4 @@ createform.externalvideoasset.url.help=Die URL der externe Video-Datei. Das Vide
|
||||||
createform.externalvideoasset.url.label=URL
|
createform.externalvideoasset.url.label=URL
|
||||||
createform.externalvideoasset.description.help=Eine kurze Beschreibung des Inhaltes des Videos.
|
createform.externalvideoasset.description.help=Eine kurze Beschreibung des Inhaltes des Videos.
|
||||||
createform.externalvideoasset.description.label=Beschreibung
|
createform.externalvideoasset.description.label=Beschreibung
|
||||||
|
fileasset.editstep.file.download.button.label=Datei herunterladen
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue