|
|
(35 intermediate revisions by 5 users not shown) |
Line 1: |
Line 1: |
− | = Overview = | + | == The Home Library has been deprecated by the new [https://wiki.gcube-system.org/gcube/StorageHub_REST_API StorageHub Service] == |
− | | + | Please use the StorageHub service for future developments: https://wiki.gcube-system.org/gcube/StorageHub_REST_API |
− | The Home Library REST interface provides a simple access to basic HL features. It is available from gCube 4.1 (home-library: 2.5; home-library-jcr: 2.5; home-library-model: 1.4). | + | |
− | | + | |
− | = Key features =
| + | |
− | Users can use the token to access to REST interface. They can access just their own files and the folders shared with them.
| + | |
− | | + | |
− | '''Home Library REST interface''' supports the following operations:
| + | |
− | * '''Create Folder''': to create a folder in the given parent path;
| + | |
− | * '''List''': to list the content of a folder;
| + | |
− | * '''Upload file''': to upload a file in a folder;
| + | |
− | * '''Download''': to download a file or a folder in ZIP format;
| + | |
− | * '''Remove''': to remove a file or a folder (including subfolders).
| + | |
− | | + | |
− | = Use cases =
| + | |
− | Users can:
| + | |
− | *use the browser to call API Methods, using username and the own token as password;
| + | |
− | *implement a Client in different languages, setting the token on the header of the request.
| + | |
− | | + | |
− | = Design =
| + | |
− | | + | |
− | == Architecture ==
| + | |
− | | + | |
− | == API ==
| + | |
− | === Get started ===
| + | |
− | Home Library REST is available from gCube 4.1.
| + | |
− | *HL_WEBAPP next: http://node11.d.d4science.research-infrastructures.eu:8080/home-library-webapp
| + | |
− | *HL_WEBAPP preProd: http://ws-repo-test.d4science.org/home-library-webapp
| + | |
− | | + | |
− | | + | |
− | For production environment, please look for the webapp's endpoint in the information system by using the [[Resource_Management | Resource Management]] portlet.
| + | |
− | The resource you need to look for/inspect is :
| + | |
− | * type : GCoreEndpoint
| + | |
− | * ServiceClass : DataAccess
| + | |
− | * ServiceName : HomeLibraryWebapp
| + | |
− | | + | |
− | === Create Folder ===
| + | |
− | | + | |
− | To create a new folder:
| + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/CreateFolder?name=$name&description=$desc&parentPath=$path
| + | |
− | </source>
| + | |
− | | + | |
− | Where:
| + | |
− | * '''name''': the name of the new folder.
| + | |
− | * '''description''': the description for the new folder.
| + | |
− | * '''parentPath''': the position where you want to save the folder.
| + | |
− | | + | |
− | Example:
| + | |
− | | + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/CreateFolder?name=myFolder&description=myDescription&parentPath=/Home/valentina.marioli/Workspace/MyDocs/
| + | |
− | </source>
| + | |
− | | + | |
− | === Delete ===
| + | |
− | | + | |
− | To remove a file or a folder:
| + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/Delete?absPath=$path
| + | |
− | </source>
| + | |
− | | + | |
− | Where:
| + | |
− | * '''absPath''': the absolute path of the file/folder to remove.
| + | |
− | | + | |
− | Output:
| + | |
− | * '''true''': if the file/folder has been correctly removed;
| + | |
− | * '''false''': otherwise.
| + | |
− | | + | |
− | === Download ===
| + | |
− | | + | |
− | This feature will be available from gCube 4.2 (home-library: 2.6; home-library-jcr: 2.6; home-library-model: 1.5).
| + | |
− | | + | |
− | To download a file or a folder in ZIP format:
| + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/Download?absPath=$path
| + | |
− | </source>
| + | |
− | | + | |
− | Where:
| + | |
− | * '''absPath''': the absolute path of the file/folder to download.
| + | |
− | | + | |
− | Output:
| + | |
− | * '''a file''': if the item to download is a file;
| + | |
− | * '''a compressed zipped folder''': if the item to download is a folder.
| + | |
− | | + | |
− | Example in Java language:
| + | |
− | | + | |
− | <source lang="java">
| + | |
− | package org.apache.jackrabbit.j2ee.rest;
| + | |
− | | + | |
− | import java.io.File;
| + | |
− | import java.io.FileOutputStream;
| + | |
− | import java.io.IOException;
| + | |
− | import java.io.InputStream;
| + | |
− | import java.net.HttpURLConnection;
| + | |
− | import java.net.URL;
| + | |
− |
| + | |
− | /**
| + | |
− | * A utility that downloads a file from a URL.
| + | |
− | *
| + | |
− | */
| + | |
− | public class HttpDownloadUtility {
| + | |
− | private static final int BUFFER_SIZE = 4096;
| + | |
− | private static final String GCUBE_TOKEN = "gcube-token";
| + | |
− |
| + | |
− | /**
| + | |
− | * Downloads a file from a URL
| + | |
− | * @param fileURL HTTP URL of the file to be downloaded
| + | |
− | * @param saveDir path of the directory to save the file
| + | |
− | * @throws IOException
| + | |
− | */
| + | |
− | public static void downloadFile(String fileURL, String saveDir)
| + | |
− | throws IOException {
| + | |
− | URL url = new URL(fileURL);
| + | |
− | HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
| + | |
− | httpConn.setRequestProperty(GCUBE_TOKEN, SecurityTokenProvider.instance.get());
| + | |
− | int responseCode = httpConn.getResponseCode();
| + | |
− |
| + | |
− | // check HTTP response code first
| + | |
− | if (responseCode == HttpURLConnection.HTTP_OK) {
| + | |
− | String fileName = "";
| + | |
− | String disposition = httpConn.getHeaderField("Content-Disposition");
| + | |
− | String contentType = httpConn.getContentType();
| + | |
− | int contentLength = httpConn.getContentLength();
| + | |
− |
| + | |
− | if (disposition != null) {
| + | |
− | // extracts file name from header field
| + | |
− | int index = disposition.indexOf("filename=");
| + | |
− | if (index > 0) {
| + | |
− | fileName = disposition.substring(index + 10,
| + | |
− | disposition.length() - 1);
| + | |
− | }
| + | |
− | } else {
| + | |
− | // extracts file name from URL
| + | |
− | fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
| + | |
− | fileURL.length());
| + | |
− | }
| + | |
− |
| + | |
− | System.out.println("Content-Type = " + contentType);
| + | |
− | System.out.println("Content-Disposition = " + disposition);
| + | |
− | System.out.println("Content-Length = " + contentLength);
| + | |
− | System.out.println("fileName = " + fileName);
| + | |
− |
| + | |
− | // opens input stream from the HTTP connection
| + | |
− | InputStream inputStream = httpConn.getInputStream();
| + | |
− | String saveFilePath = saveDir + File.separator + fileName;
| + | |
− |
| + | |
− | // opens an output stream to save into file
| + | |
− | FileOutputStream outputStream = new FileOutputStream(saveFilePath);
| + | |
− |
| + | |
− | int bytesRead = -1;
| + | |
− | byte[] buffer = new byte[BUFFER_SIZE];
| + | |
− | while ((bytesRead = inputStream.read(buffer)) != -1) {
| + | |
− | outputStream.write(buffer, 0, bytesRead);
| + | |
− | }
| + | |
− |
| + | |
− | outputStream.close();
| + | |
− | inputStream.close();
| + | |
− |
| + | |
− | System.out.println("File downloaded");
| + | |
− | } else {
| + | |
− | System.out.println("No file to download. Server replied HTTP code: " + responseCode);
| + | |
− | }
| + | |
− | httpConn.disconnect();
| + | |
− | }
| + | |
− | }
| + | |
− | </source>
| + | |
− | | + | |
− | Note that in the static method downloadFile(), we have to check HTTP response code from the server to make sure the URL is available (HTTP status 200). Then we extract the file name either from the HTTP header Content-Disposition (in case the URL is an indirect link), or from the URL itself (in case the URL is the direct link). We also print out some debugging information like Content-Type, Content-Disposition, Content-Length and file name.
| + | |
− | | + | |
− | And here is a test program which employs the utility class above:
| + | |
− | | + | |
− | <source lang="java">
| + | |
− | import java.io.IOException;
| + | |
− |
| + | |
− | public class HttpDownloader {
| + | |
− |
| + | |
− | public static void main(String[] args) {
| + | |
− | SecurityTokenProvider.instance.set(HERE_YOUR_TOKEN);
| + | |
− | String absPath = "/Home/test.user/Workspace/MyFolder/";
| + | |
− | String fileURL = HL_WEBAPP + "/rest/Download?absPath=" + absPath;
| + | |
− | String saveDir = "/home/user/Downloads/";
| + | |
− | try {
| + | |
− | HttpDownloadUtility.downloadFile(fileURL, saveDir);
| + | |
− | } catch (IOException ex) {
| + | |
− | ex.printStackTrace();
| + | |
− | }
| + | |
− | }
| + | |
− | }
| + | |
− | </source>
| + | |
− | | + | |
− | This program downloads the folder "MyFolder" as zip folder (MyFolder.zip) and saves it into the directory "/home/user/Downloads/".
| + | |
− | | + | |
− | It would produce the following output:
| + | |
− | | + | |
− | <source lang="java">
| + | |
− | Content-Type = application/zip
| + | |
− | Content-Disposition = attachment; filename="MyFolder.zip"
| + | |
− | Content-Length = 8894049
| + | |
− | fileName = MyFolder.zip
| + | |
− | File downloaded
| + | |
− | | + | |
− | </source>
| + | |
− | | + | |
− | === Get Public Link ===
| + | |
− | To get a public link of a file:
| + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/GetPublicLink?absPath=$path
| + | |
− | </source>
| + | |
− | | + | |
− | Where:
| + | |
− | * '''absPath''': the absolute path of the folder to list;
| + | |
− | * '''shortUrl''': true to get a short url, false otherwise. It will be false by default.
| + | |
− | | + | |
− | Example:
| + | |
− | | + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/GetPublicLink?absPath=/Home/valentina.marioli/Workspace/test.txt&shortUrl=true</source>
| + | |
− | Output:
| + | |
− | A link to the file.
| + | |
− | | + | |
− | '''Using cURL:'''
| + | |
− | <source lang="php">
| + | |
− | curl --header "gcube-token: ***********************" /
| + | |
− | HL_WEBAPP/rest/GetPublicLink?absPath=/Home/test.user/Workspace/myfile.pdf&shortUrl=true
| + | |
− | </source>
| + | |
− | | + | |
− | === List ===
| + | |
− | To list the content of a folder:
| + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/List?absPath=$path
| + | |
− | </source>
| + | |
− | | + | |
− | Where:
| + | |
− | * '''absPath''': the absolute path of the folder to list;
| + | |
− | * '''showHidden''': true to show hidden files, false otherwise. It will be false by default.
| + | |
− | | + | |
− | Returns a list of entries with:
| + | |
− | * '''name''': the name of the file/folder;
| + | |
− | * '''flag''': true if the item is a folder, false if it is a file.
| + | |
− | | + | |
− | Output:
| + | |
− | <source lang="xml">
| + | |
− | <map>
| + | |
− | <entry>
| + | |
− | <string>myFolder</string>
| + | |
− | <boolean>true</boolean>
| + | |
− | </entry>
| + | |
− | <entry>
| + | |
− | <string>home-library-jcr-2.5.0-SNAPSHOT.jar</string>
| + | |
− | <boolean>false</boolean>
| + | |
− | </entry>
| + | |
− | <entry>
| + | |
− | <string>home-library-2.5.0-SNAPSHOT.jar</string>
| + | |
− | <boolean>false</boolean>
| + | |
− | </entry>
| + | |
− | <entry>
| + | |
− | <string>home-library-common-2.5.0-SNAPSHOT.jar</string>
| + | |
− | <boolean>false</boolean>
| + | |
− | </entry>
| + | |
− | <entry>
| + | |
− | <string>anotherFolder</string>
| + | |
− | <boolean>true</boolean>
| + | |
− | </entry>
| + | |
− | </map>
| + | |
− | </source>
| + | |
− | | + | |
− | | + | |
− | | + | |
− | '''Using cURL:'''
| + | |
− | <source lang="php">
| + | |
− | curl --header "gcube-token: ***********************" /
| + | |
− | HL_WEBAPP/rest/List?absPath=/Home/test.user/Workspace/
| + | |
− | </source>
| + | |
− | | + | |
− | === Unzip ===
| + | |
− | | + | |
− | To upload a zip file in a specific folder.
| + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/Unzip?name=$name&parentPath=$path&replace=$flag&hardReplace=$flag
| + | |
− | </source>
| + | |
− | | + | |
− | Where:
| + | |
− | * '''name''': the name of the file to unzip;
| + | |
− | * '''parentPath''': the path to save the decompressed folder;
| + | |
− | * '''replace''': true to overwrite the files with the same names; false otherwise.
| + | |
− | * '''hardReplace''': true to delete the destination folder, if it already exists; false otherwise.
| + | |
− | | + | |
− | The zip file has to be attached to the http request.
| + | |
− | | + | |
− | Output:
| + | |
− | * the path of the decompressed folder.
| + | |
− | | + | |
− | How it works:
| + | |
− | * if '''replace''' is true but a file with the same name does not exist in such folder, the file will be created;
| + | |
− | * if '''replace''' is false and a file with the same name does not exist in such folder, the file will be created;
| + | |
− | * if '''replace''' is true and a file with the same name already exists in such folder, the file will be overwritten;
| + | |
− | * if '''replace''' is false and a file with the same name already exists in such folder, the file will be created adding a progressive number to the destination folder name.
| + | |
− | | + | |
− | | + | |
− | '''Using CURL:'''
| + | |
− | <source lang="php">
| + | |
− | curl --header "gcube-token: ************************" /
| + | |
− | --request POST --data-binary @/home/valentina/test.zip /
| + | |
− | --header "Content-Type: application/zip" /
| + | |
− | 'HL_WEBAPP/rest/Unzip?name=test.zip&parentPath=/Home/valentina.marioli/Workspace/testaa&replace=true&hardReplace=true'
| + | |
− | | + | |
− | | + | |
− | </source>
| + | |
− | | + | |
− | === Upload File ===
| + | |
− | | + | |
− | To upload a file, if it does not already exist:
| + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/Upload?name=$name&description=$description&parentPath=$path
| + | |
− | </source>
| + | |
− | | + | |
− | Where:
| + | |
− | * '''name''': the file to upload
| + | |
− | * '''description''': a description for the file
| + | |
− | * '''parentPath''': the position where you want to save the file.
| + | |
− | | + | |
− | If you want to skip mimetype and size detect steps because you already know them, you can pass them as parameter:
| + | |
− | <source lang="java">
| + | |
− | HL_WEBAPP/rest/Upload?name=$name&description=$description&parentPath=$path&mimetype=$mimetype&size=$size
| + | |
− | </source>
| + | |
− | | + | |
− | '''Using CURL:'''
| + | |
− | <source lang="php">
| + | |
− | curl --header "gcube-token: ************************" /
| + | |
− | --request POST --data-binary @/home/valentina/test.jpg /
| + | |
− | --header "Content-Type: image/jpeg" /
| + | |
− | 'HL_WEBAPP/rest/Upload?name=test.jpg&description=test&parentPath=/Home/test.user/Workspace/myfolder'
| + | |
− | </source>
| + | |
− | | + | |
− | '''Using Java:'''
| + | |
− | <source lang="java">
| + | |
− | package org.apache.jackrabbit.j2ee.rest;
| + | |
− | | + | |
− | import java.io.BufferedReader;
| + | |
− | import java.io.File;
| + | |
− | import java.io.InputStreamReader;
| + | |
− | import java.io.OutputStream;
| + | |
− | import java.net.HttpURLConnection;
| + | |
− | import java.net.URL;
| + | |
− | import java.net.URLEncoder;
| + | |
− | import java.nio.file.Files;
| + | |
− | | + | |
− | import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
| + | |
− | import com.thoughtworks.xstream.XStream;
| + | |
− | | + | |
− | public class UploadFileRest {
| + | |
− | | + | |
− | private static final String DEFAULT_IMAGE = "default.jpg";
| + | |
− | private static final String ROOT_PATH = "/Home/test.user/Workspace/";
| + | |
− | private static final String GCUBE_TOKEN = "gcube-token";
| + | |
− | | + | |
− | public static void main(String[] args) throws Exception {
| + | |
− |
| + | |
− | SecurityTokenProvider.instance.set(HERE_YOUR_TOKEN);
| + | |
− | URL imageURL = UploadFileRest.class.getClassLoader().getResource(DEFAULT_IMAGE);
| + | |
− | File file = new File(imageURL.getFile());
| + | |
− | | + | |
− | byte[] image = Files.readAllBytes(file.toPath());
| + | |
− | System.out.println(uploadFile(image, DEFAULT_IMAGE, "my description", ROOT_PATH));
| + | |
− | | + | |
− | }
| + | |
− |
| + | |
− |
| + | |
− | public static String uploadFile(byte[] in, String name, String description, String parentPath) throws Exception {
| + | |
− | XStream xstream = new XStream();
| + | |
− | String uri = HL_WEBAPP + "/rest/Upload?" + "name=" + name+ "&description=" + URLEncoder.encode(description, "UTF-8") +
| + | |
− | "&parentPath=" + URLEncoder.encode(parentPath, "UTF-8");
| + | |
− |
| + | |
− | URL url = new URL(uri);
| + | |
− | HttpURLConnection connection = (HttpURLConnection)url.openConnection();
| + | |
− | connection.setRequestProperty(GCUBE_TOKEN, SecurityTokenProvider.instance.get());
| + | |
− | connection.setDoInput(true);
| + | |
− | connection.setDoOutput(true);
| + | |
− | connection.setUseCaches(false);
| + | |
− | connection.setRequestProperty("Content-Type", "image/jpeg");
| + | |
− | connection.setRequestMethod("POST");
| + | |
− | TokenUtility.setHeader(connection);
| + | |
− |
| + | |
− | // Write file to response.
| + | |
− | OutputStream output = connection.getOutputStream();
| + | |
− | output.write(in);
| + | |
− | output.close();
| + | |
− |
| + | |
− | BufferedReader r = new BufferedReader(new InputStreamReader(connection.getInputStream()));
| + | |
− | | + | |
− | StringBuffer response = new StringBuffer();
| + | |
− | String inputLine;
| + | |
− | while ((inputLine = r.readLine()) != null) {
| + | |
− | response.append(inputLine);
| + | |
− | }
| + | |
− | | + | |
− | String xmlOut = response.toString();
| + | |
− | return (String) xstream.fromXML(xmlOut);
| + | |
− | }
| + | |
− |
| + | |
− | }
| + | |
− | | + | |
− | </source>
| + | |