Unverified Commit c0d17edf authored by Gautier de Saint Martin Lacaze's avatar Gautier de Saint Martin Lacaze Committed by GitHub
Browse files

Merge pull request #776 from alb-i986/upload-InputStream

Upload: accept an InputStream besides a File
parents 15fc264c 1a1c3b21
package org.gitlab4j.api;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import javax.ws.rs.NotAuthorizedException;
......@@ -369,7 +370,7 @@ public abstract class AbstractApi implements Constants {
* @param expectedStatus the HTTP status that should be returned from the server
* @param name the name for the form field that contains the file name
* @param fileToUpload a File instance pointing to the file to upload
* @param mediaType the content-type of the uploaded file, if null will be determined from fileToUpload
* @param mediaType unused; will be removed in the next major version
* @param pathArgs variable list of arguments used to build the URI
* @return a ClientResponse instance with the data returned from the endpoint
* @throws GitLabApiException if any exception occurs during execution
......@@ -382,6 +383,14 @@ public abstract class AbstractApi implements Constants {
}
}
protected Response upload(Response.Status expectedStatus, String name, InputStream inputStream, String filename, String mediaType, Object... pathArgs) throws GitLabApiException {
try {
return validate(getApiClient().upload(name, inputStream, filename, mediaType, pathArgs), expectedStatus);
} catch (Exception e) {
throw handle(e);
}
}
/**
* Perform a file upload with the specified File instance and path objects, returning
* a ClientResponse instance with the data returned from the endpoint.
......@@ -389,7 +398,7 @@ public abstract class AbstractApi implements Constants {
* @param expectedStatus the HTTP status that should be returned from the server
* @param name the name for the form field that contains the file name
* @param fileToUpload a File instance pointing to the file to upload
* @param mediaType the content-type of the uploaded file, if null will be determined from fileToUpload
* @param mediaType unused; will be removed in the next major version
* @param url the fully formed path to the GitLab API endpoint
* @return a ClientResponse instance with the data returned from the endpoint
* @throws GitLabApiException if any exception occurs during execution
......@@ -409,7 +418,7 @@ public abstract class AbstractApi implements Constants {
* @param expectedStatus the HTTP status that should be returned from the server
* @param name the name for the form field that contains the file name
* @param fileToUpload a File instance pointing to the file to upload
* @param mediaType the content-type of the uploaded file, if null will be determined from fileToUpload
* @param mediaType unused; will be removed in the next major version
* @param formData the Form containing the name/value pairs
* @param url the fully formed path to the GitLab API endpoint
* @return a ClientResponse instance with the data returned from the endpoint
......
......@@ -2,6 +2,7 @@ package org.gitlab4j.api;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.URL;
import java.security.GeneralSecurityException;
......@@ -13,7 +14,6 @@ import java.util.Map;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
......@@ -30,7 +30,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import org.gitlab4j.api.Constants.TokenType;
import org.gitlab4j.api.GitLabApi.ApiVersion;
import org.gitlab4j.api.utils.JacksonJson;
......@@ -39,11 +38,13 @@ import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.JerseyClientBuilder;
import org.glassfish.jersey.media.multipart.BodyPart;
import org.glassfish.jersey.media.multipart.Boundary;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
/**
......@@ -561,14 +562,13 @@ public class GitLabApiClient implements AutoCloseable {
*
* @param name the name for the form field that contains the file name
* @param fileToUpload a File instance pointing to the file to upload
* @param mediaTypeString the content-type of the uploaded file, if null will be determined from fileToUpload
* @param mediaTypeString unused; will be removed in the next major version
* @param pathArgs variable list of arguments used to build the URI
* @return a ClientResponse instance with the data returned from the endpoint
* @throws IOException if an error occurs while constructing the URL
*/
protected Response upload(String name, File fileToUpload, String mediaTypeString, Object... pathArgs) throws IOException {
URL url = getApiUrl(pathArgs);
return (upload(name, fileToUpload, mediaTypeString, null, url));
return upload(name, fileToUpload, mediaTypeString, null, pathArgs);
}
/**
......@@ -577,7 +577,7 @@ public class GitLabApiClient implements AutoCloseable {
*
* @param name the name for the form field that contains the file name
* @param fileToUpload a File instance pointing to the file to upload
* @param mediaTypeString the content-type of the uploaded file, if null will be determined from fileToUpload
* @param mediaTypeString unused; will be removed in the next major version
* @param formData the Form containing the name/value pairs
* @param pathArgs variable list of arguments used to build the URI
* @return a ClientResponse instance with the data returned from the endpoint
......@@ -594,30 +594,38 @@ public class GitLabApiClient implements AutoCloseable {
*
* @param name the name for the form field that contains the file name
* @param fileToUpload a File instance pointing to the file to upload
* @param mediaTypeString the content-type of the uploaded file, if null will be determined from fileToUpload
* @param mediaTypeString unused; will be removed in the next major version
* @param formData the Form containing the name/value pairs
* @param url the fully formed path to the GitLab API endpoint
* @return a ClientResponse instance with the data returned from the endpoint
* @throws IOException if an error occurs while constructing the URL
*/
protected Response upload(String name, File fileToUpload, String mediaTypeString, Form formData, URL url) throws IOException {
FileDataBodyPart filePart = new FileDataBodyPart(name, fileToUpload);
return upload(filePart, formData, url);
}
MediaType mediaType = (mediaTypeString != null ? MediaType.valueOf(mediaTypeString) : null);
try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
protected Response upload(String name, InputStream inputStream, String filename, String mediaTypeString, Object... pathArgs) throws IOException {
URL url = getApiUrl(pathArgs);
return (upload(name, inputStream, filename, mediaTypeString, null, url));
}
protected Response upload(String name, InputStream inputStream, String filename, String mediaTypeString, Form formData, URL url) throws IOException {
StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart(name, inputStream, filename);
return upload(streamDataBodyPart, formData, url);
}
protected Response upload(BodyPart bodyPart, Form formData, URL url) throws IOException {
try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
if (formData != null) {
MultivaluedMap<String, String> formParams = formData.asMap();
formParams.forEach((key, values) -> {
formData.asMap().forEach((key, values) -> {
if (values != null) {
values.forEach(value -> multiPart.field(key, value));
}
});
}
FileDataBodyPart filePart = mediaType != null ?
new FileDataBodyPart(name, fileToUpload, mediaType) :
new FileDataBodyPart(name, fileToUpload);
multiPart.bodyPart(filePart);
multiPart.bodyPart(bodyPart);
final Entity<?> entity = Entity.entity(multiPart, Boundary.addBoundary(multiPart.getMediaType()));
return (invocation(url, null).post(entity));
}
......
......@@ -24,6 +24,7 @@
package org.gitlab4j.api;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
......@@ -32,12 +33,10 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.gitlab4j.api.GitLabApi.ApiVersion;
import org.gitlab4j.api.models.AccessLevel;
import org.gitlab4j.api.models.AccessRequest;
......@@ -2565,7 +2564,7 @@ public class ProjectApi extends AbstractApi implements Constants {
*
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required
* @param fileToUpload the File instance of the file to upload, required
* @param mediaType the media type of the file to upload, optional
* @param mediaType unused; will be removed in the next major version
* @return a FileUpload instance with information on the just uploaded file
* @throws GitLabApiException if any exception occurs
*/
......@@ -2574,6 +2573,22 @@ public class ProjectApi extends AbstractApi implements Constants {
return (response.readEntity(FileUpload.class));
}
/**
* Uploads some data in an {@link InputStream} to the specified project,
* to be used in an issue or merge request description, or a comment.
*
* <pre><code>GitLab Endpoint: POST /projects/:id/uploads</code></pre>
*
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required
* @param inputStream the data to upload, required
* @return a FileUpload instance with information on the just uploaded file
* @throws GitLabApiException if any exception occurs
*/
public FileUpload uploadFile(Object projectIdOrPath, InputStream inputStream, String filename, String mediaType) throws GitLabApiException {
Response response = upload(Response.Status.CREATED, "file", inputStream, filename, mediaType, "projects", getProjectIdOrPath(projectIdOrPath), "uploads");
return (response.readEntity(FileUpload.class));
}
/**
* Get the project's push rules.
*
......
package org.gitlab4j.api;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.assumeTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Map;
import org.gitlab4j.api.models.FileUpload;
import org.gitlab4j.api.models.Project;
import org.junit.Before;
......@@ -18,17 +22,17 @@ import org.junit.runners.MethodSorters;
/**
* In order for these tests to run you must set the following properties in test-gitlab4j.properties
*
*
* TEST_NAMESPACE
* TEST_PROJECT_NAME
* TEST_HOST_URL
* TEST_PRIVATE_TOKEN
*
*
* If any of the above are NULL, all tests in this class will be skipped.
*/
@Category(IntegrationTest.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestFileUpload extends AbstractIntegrationTest {
public class TestUpload extends AbstractIntegrationTest {
// The following needs to be set to your test repository
private static final String TEST_PROXY_URI = HelperUtils.getProperty("TEST_PROXY_URI");
......@@ -37,7 +41,7 @@ public class TestFileUpload extends AbstractIntegrationTest {
private static GitLabApi gitLabApi;
public TestFileUpload() {
public TestUpload() {
super();
}
......@@ -93,4 +97,21 @@ public class TestFileUpload extends AbstractIntegrationTest {
gitLabApi.close();
}
@Test
public void testInputStreamUpload() throws GitLabApiException, FileNotFoundException {
Project project = gitLabApi.getProjectApi().getProject(TEST_NAMESPACE, TEST_PROJECT_NAME);
assertNotNull(project);
String filename = "README.md";
File fileToUpload = new File(filename);
FileUpload fileUpload = gitLabApi.getProjectApi().uploadFile(
project.getId(), new FileInputStream(fileToUpload), filename, null);
assertNotNull(fileUpload);
assertThat(fileUpload.getUrl(), endsWith(filename));
assertThat(fileUpload.getAlt(), equalTo(filename));
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment