001/* 002 * (C) Copyright 2015-2016 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 * Estelle Giuy <egiuly@nuxeo.com> 019 */ 020package org.nuxeo.ecm.core.io.download; 021 022import java.io.IOException; 023import java.io.OutputStream; 024import java.io.Serializable; 025import java.util.List; 026import java.util.Map; 027import java.util.function.Consumer; 028import java.util.function.Supplier; 029 030import javax.servlet.http.HttpServletRequest; 031import javax.servlet.http.HttpServletResponse; 032 033import org.nuxeo.ecm.core.api.Blob; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.impl.blob.AsyncBlob; 036 037/** 038 * This service allows the download of blobs to a HTTP response. 039 * 040 * @since 7.3 041 */ 042public interface DownloadService { 043 044 String EVENT_NAME = "download"; 045 046 String NXFILE = "nxfile"; 047 048 String NXDOWNLOADINFO = "nxdownloadinfo"; 049 050 /** 051 * @since 9.3 052 */ 053 String NXBLOBSTATUS = "nxblobstatus"; 054 055 String NXBIGBLOB = "nxbigblob"; 056 057 /** @deprecated since 9.1, use nxbigblob instead */ 058 @Deprecated 059 String NXBIGZIPFILE = "nxbigzipfile"; 060 061 /** @deprecated since 7.4, use nxfile instead */ 062 @Deprecated 063 String NXBIGFILE = "nxbigfile"; 064 065 String BLOBHOLDER_PREFIX = "blobholder:"; 066 067 String BLOBHOLDER_0 = "blobholder:0"; 068 069 /** 070 * The transient store parameter name for storing an error if any. Stored entry must 071 */ 072 String TRANSIENT_STORE_PARAM_ERROR = "error"; 073 074 String TRANSIENT_STORE_PARAM_PROGRESS = "progress"; 075 076 String TRANSIENT_STORE_STORE_NAME = "download"; 077 078 public static class ByteRange { 079 080 private final long start; 081 082 private final long end; 083 084 public ByteRange(long start, long end) { 085 this.start = start; 086 this.end = end; 087 } 088 089 public long getStart() { 090 return start; 091 } 092 093 public long getEnd() { 094 return end; 095 } 096 097 public long getLength() { 098 return end - start + 1; 099 } 100 } 101 102 /** 103 * Stores the blobs for later download. 104 * 105 * @param the list of blobs to store 106 * @return the store key used for retrieving the blobs (@see {@link DownloadService#getDownloadUrl(String)} 107 * @since 9.1 108 */ 109 String storeBlobs(List<Blob> blobs); 110 111 /** 112 * Gets the URL to use to download the blob at the given xpath in the given document. 113 * <p> 114 * The URL is relative to the Nuxeo Web Application context. 115 * <p> 116 * Returns something like {@code nxbigfile/reponame/docuuid/blobholder:0/foo.jpg} 117 * 118 * @param doc the document 119 * @param xpath the blob's xpath or blobholder index, or {@code null} for default 120 * @param filename the blob's filename, or {@code null} for default 121 * @return the download URL 122 */ 123 String getDownloadUrl(DocumentModel doc, String xpath, String filename); 124 125 /** 126 * Gets the URL to use to download the blob at the given xpath in the given document. 127 * <p> 128 * The URL is relative to the Nuxeo Web Application context. 129 * <p> 130 * Returns something like {@code nxbigfile/reponame/docuuid/blobholder:0/foo.jpg} 131 * 132 * @param repositoryName the document repository 133 * @param docId the document id 134 * @param xpath the blob's xpath or blobholder index, or {@code null} for default 135 * @param filename the blob's filename, or {@code null} for default 136 * @return the download URL 137 */ 138 String getDownloadUrl(String repositoryName, String docId, String xpath, String filename); 139 140 /** 141 * Gets the URL to use to download the blobs identified by a storage key. 142 * <p> 143 * The URL is relative to the Nuxeo Web Application context. 144 * <p> 145 * Returns something like {@code nxbigblob/key} 146 * 147 * @param key The key of stored blobs to download 148 * @return the download URL 149 * @since 9.1 150 */ 151 String getDownloadUrl(String storeKey); 152 153 /** 154 * Finds a document's blob given the URL to use to download the blob. 155 * 156 * @param url the URL to use to download the blob 157 * @return the blob, or {@code null} if not found 158 * @since 9.1 159 */ 160 Blob resolveBlobFromDownloadUrl(String url); 161 162 /** 163 * Handles the download of a document. 164 * 165 * @param req the request 166 * @param resp the response 167 * @param baseUrl the request baseUrl 168 * @param path the request path, without the context 169 * @since 9.1 170 */ 171 void handleDownload(HttpServletRequest req, HttpServletResponse resp, String baseUrl, String path) 172 throws IOException; 173 174 /** 175 * Triggers a {@link AsyncBlob} download which gives information about an asynchronous blob. 176 * 177 * @param storeKey the stored blobs key 178 * @param reason the download reason 179 * @since 9.3 180 */ 181 void downloadBlobStatus(HttpServletRequest request, HttpServletResponse response, String storeKey, String reason) 182 throws IOException; 183 184 /** 185 * Triggers a blobs download. Once the temporary blobs are transfered from the store, they are automatically 186 * deleted. The returned HTTP Status Code is 200 if the blob is ready or 202 if it is still being processed. 187 * 188 * @param storeKey the stored blobs key 189 * @param reason the download reason 190 * @since 9.1 191 */ 192 void downloadBlob(HttpServletRequest request, HttpServletResponse response, String storeKey, String reason) throws IOException; 193 194 /** 195 * Triggers a blob download. 196 * 197 * @param doc the document, if available 198 * @param xpath the blob's xpath or blobholder index, if available 199 * @param blob the blob, if already fetched 200 * @param filename the filename to use 201 * @param reason the download reason 202 */ 203 void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath, 204 Blob blob, String filename, String reason) throws IOException; 205 206 /** 207 * Triggers a blob download. 208 * 209 * @param doc the document, if available 210 * @param xpath the blob's xpath or blobholder index, if available 211 * @param blob the blob, if already fetched 212 * @param filename the filename to use 213 * @param reason the download reason 214 * @param extendedInfos an optional map of extended informations to log 215 */ 216 void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath, 217 Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos) throws IOException; 218 219 /** 220 * Triggers a blob download. 221 * 222 * @param doc the document, if available 223 * @param xpath the blob's xpath or blobholder index, if available 224 * @param blob the blob, if already fetched 225 * @param filename the filename to use 226 * @param reason the download reason 227 * @param extendedInfos an optional map of extended informations to log 228 * @param inline if not null, force the inline flag for content-disposition 229 */ 230 void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath, 231 Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos, Boolean inline) 232 throws IOException; 233 234 /** 235 * Triggers a blob download. The actual byte transfer is done through a {@link DownloadExecutor}. 236 * 237 * @param doc the document, if available 238 * @param xpath the blob's xpath or blobholder index, if available 239 * @param blob the blob, if already fetched 240 * @param filename the filename to use 241 * @param reason the download reason 242 * @param extendedInfos an optional map of extended informations to log 243 * @param inline if not null, force the inline flag for content-disposition 244 * @param blobTransferer the transferer of the actual blob 245 * @since 7.10 246 */ 247 void downloadBlob(HttpServletRequest request, HttpServletResponse response, DocumentModel doc, String xpath, 248 Blob blob, String filename, String reason, Map<String, Serializable> extendedInfos, Boolean inline, 249 Consumer<ByteRange> blobTransferer) throws IOException; 250 251 /** 252 * Copies the blob stream at the given byte range into the supplied {@link OutputStream}. 253 * 254 * @param blob the blob 255 * @param byteRange the byte range 256 * @param outputStreamSupplier the {@link OutputStream} supplier 257 * @since 7.10 258 */ 259 void transferBlobWithByteRange(Blob blob, ByteRange byteRange, Supplier<OutputStream> outputStreamSupplier); 260 261 /** 262 * Logs a download. 263 * 264 * @param doc the doc for which this download occurs, if available 265 * @param blobXPath the blob's xpath or blobholder index, if available 266 * @param filename the filename 267 * @param reason the download reason 268 * @param extendedInfos an optional map of extended informations to log 269 */ 270 void logDownload(DocumentModel doc, String blobXPath, String filename, String reason, 271 Map<String, Serializable> extendedInfos); 272 273 /** 274 * Finds a document's blob given an xpath or blobholder index 275 * 276 * @param doc the document 277 * @param xpath the xpath or blobholder index 278 * @return the blob, or {@code null} if not found 279 */ 280 Blob resolveBlob(DocumentModel doc, String xpath); 281 282 /** 283 * Finds a document's blob. 284 * 285 * @param doc the document 286 * @return the blob, or {@code null} if not available 287 * @since 9.3 288 */ 289 Blob resolveBlob(DocumentModel doc); 290 291 /** 292 * Checks whether the download of the blob is allowed. 293 * 294 * @param doc the doc for which this download occurs, if available 295 * @param blobXPath the blob's xpath or blobholder index, if available 296 * @param blob the blob 297 * @param reason the download reason 298 * @param extendedInfos an optional map of extended informations to log 299 * @return {@code true} if download is allowed 300 * @since 7.10 301 */ 302 boolean checkPermission(DocumentModel doc, String xpath, Blob blob, String reason, 303 Map<String, Serializable> extendedInfos); 304 305}