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}