mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 14:07:55 +01:00
Download all files from a document as ZIP
This commit is contained in:
parent
ae566018d6
commit
34e3ac5478
@ -56,4 +56,29 @@ public class MimeTypeUtil {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a file extension linked to a MIME type.
|
||||||
|
*
|
||||||
|
* @param mimeType MIME type
|
||||||
|
* @return File extension
|
||||||
|
*/
|
||||||
|
public static String getFileExtension(String mimeType) {
|
||||||
|
switch (mimeType) {
|
||||||
|
case MimeType.APPLICATION_ZIP:
|
||||||
|
return "zip";
|
||||||
|
case MimeType.IMAGE_GIF:
|
||||||
|
return "gif";
|
||||||
|
case MimeType.IMAGE_JPEG:
|
||||||
|
return "jpg";
|
||||||
|
case MimeType.IMAGE_PNG:
|
||||||
|
return "png";
|
||||||
|
case MimeType.IMAGE_X_ICON:
|
||||||
|
return "ico";
|
||||||
|
case MimeType.APPLICATION_PDF:
|
||||||
|
return "pdf";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
- Automatic backup system using Quartz (server)
|
- Automatic backup system using Quartz (server)
|
||||||
- Handle error while uploading a file
|
- Handle error while uploading a file
|
||||||
- Download all files as zip (docs & share)
|
|
||||||
|
@ -11,6 +11,8 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import javax.persistence.NoResultException;
|
import javax.persistence.NoResultException;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
@ -372,4 +374,75 @@ public class FileResource extends BaseResource {
|
|||||||
.header("Expires", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(new Date().getTime() + 3600000 * 24))
|
.header("Expires", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(new Date().getTime() + 3600000 * 24))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all files from a document, zipped.
|
||||||
|
*
|
||||||
|
* @param documentId Document ID
|
||||||
|
* @return Response
|
||||||
|
* @throws JSONException
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("zip")
|
||||||
|
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
|
public Response zip(
|
||||||
|
@QueryParam("id") String documentId,
|
||||||
|
@QueryParam("share") String shareId) throws JSONException {
|
||||||
|
authenticate();
|
||||||
|
|
||||||
|
// Get the document
|
||||||
|
DocumentDao documentDao = new DocumentDao();
|
||||||
|
Document document;
|
||||||
|
try {
|
||||||
|
document = documentDao.getDocument(documentId);
|
||||||
|
|
||||||
|
// Check document visibility
|
||||||
|
ShareDao shareDao = new ShareDao();
|
||||||
|
if (!shareDao.checkVisibility(document, principal.getId(), shareId)) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
} catch (NoResultException e) {
|
||||||
|
throw new ClientException("DocumentNotFound", MessageFormat.format("Document not found: {0}", documentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get files and user associated with this document
|
||||||
|
FileDao fileDao = new FileDao();
|
||||||
|
UserDao userDao = new UserDao();
|
||||||
|
final List<File> fileList = fileDao.getByDocumentId(documentId);
|
||||||
|
final User user = userDao.getById(document.getUserId());
|
||||||
|
|
||||||
|
// Create the ZIP stream
|
||||||
|
StreamingOutput stream = new StreamingOutput() {
|
||||||
|
@Override
|
||||||
|
public void write(OutputStream outputStream) throws IOException, WebApplicationException {
|
||||||
|
try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) {
|
||||||
|
// Add each file to the ZIP stream
|
||||||
|
int index = 0;
|
||||||
|
for (File file : fileList) {
|
||||||
|
java.io.File storedfile = Paths.get(DirectoryUtil.getStorageDirectory().getPath(), file.getId()).toFile();
|
||||||
|
InputStream fileInputStream = new FileInputStream(storedfile);
|
||||||
|
|
||||||
|
// Add the decrypted file to the ZIP stream
|
||||||
|
try (InputStream decryptedStream = EncryptionUtil.decryptInputStream(fileInputStream, user.getPrivateKey())) {
|
||||||
|
ZipEntry zipEntry = new ZipEntry(index + "." + MimeTypeUtil.getFileExtension(file.getMimeType()));
|
||||||
|
zipOutputStream.putNextEntry(zipEntry);
|
||||||
|
ByteStreams.copy(decryptedStream, zipOutputStream);
|
||||||
|
zipOutputStream.closeEntry();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new WebApplicationException(e);
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write to the output
|
||||||
|
return Response.ok(stream)
|
||||||
|
.header("Content-Type", "application/zip")
|
||||||
|
.header("Content-Disposition", "attachment; filename=\"" + document.getTitle().replaceAll("\\W+", "_") + ".zip\"")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>{{ document.title }} <small>{{ document.create_date | date: 'yyyy-MM-dd' }}</small> <img ng-if="document" ng-src="img/flag/{{ document.language }}.png" title="{{ document.language }}" /></h1>
|
<h1>
|
||||||
|
{{ document.title }} <small>{{ document.create_date | date: 'yyyy-MM-dd' }}</small>
|
||||||
|
<img ng-if="document" ng-src="img/flag/{{ document.language }}.png" title="{{ document.language }}" />
|
||||||
|
<a ng-href="../api/file/zip?id={{ document.id }}" class="btn btn-default" title="Download all files">
|
||||||
|
<span class="glyphicon glyphicon-compressed"></span>
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
<button class="btn btn-sm btn-info" ng-click="share()">
|
<button class="btn btn-sm btn-info" ng-click="share()">
|
||||||
<span class="glyphicon glyphicon-share"></span> Share
|
<span class="glyphicon glyphicon-share"></span> Share
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="well col-md-12">
|
<div class="well col-md-12">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>{{ document.title }} <small>{{ document.create_date | date: 'yyyy-MM-dd' }}</small></h1>
|
<h1>
|
||||||
|
{{ document.title }} <small>{{ document.create_date | date: 'yyyy-MM-dd' }}</small>
|
||||||
|
<a ng-href="../api/file/zip?id={{ document.id }}&share={{ $stateParams.shareId }}" class="btn btn-default" title="Download all files">
|
||||||
|
<span class="glyphicon glyphicon-compressed"></span>
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
<ul class="list-inline">
|
<ul class="list-inline">
|
||||||
<li ng-repeat="tag in document.tags"><span class="label label-info" ng-style="{ 'background': tag.color }">{{ tag.name }}</span></li>
|
<li ng-repeat="tag in document.tags"><span class="label label-info" ng-style="{ 'background': tag.color }">{{ tag.name }}</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -160,6 +160,16 @@ public class TestFileResource extends BaseJerseyTest {
|
|||||||
Assert.assertEquals(file2Id, files.getJSONObject(0).getString("id"));
|
Assert.assertEquals(file2Id, files.getJSONObject(0).getString("id"));
|
||||||
Assert.assertEquals(file1Id, files.getJSONObject(1).getString("id"));
|
Assert.assertEquals(file1Id, files.getJSONObject(1).getString("id"));
|
||||||
|
|
||||||
|
// Get a ZIP from all files
|
||||||
|
fileResource = resource().path("/file/zip");
|
||||||
|
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken));
|
||||||
|
getParams = new MultivaluedMapImpl();
|
||||||
|
getParams.putSingle("id", document1Id);
|
||||||
|
response = fileResource.queryParams(getParams).get(ClientResponse.class);
|
||||||
|
is = response.getEntityInputStream();
|
||||||
|
fileBytes = ByteStreams.toByteArray(is);
|
||||||
|
Assert.assertEquals(MimeType.APPLICATION_ZIP, MimeTypeUtil.guessMimeType(fileBytes));
|
||||||
|
|
||||||
// Deletes a file
|
// Deletes a file
|
||||||
fileResource = resource().path("/file/" + file1Id);
|
fileResource = resource().path("/file/" + file1Id);
|
||||||
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken));
|
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken));
|
||||||
|
Loading…
Reference in New Issue
Block a user