Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/main/java/org/gitlab4j/api/AbstractApi.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.gitlab4j.api;

import java.io.File;
import java.io.InputStream;
import java.net.URL;

import javax.ws.rs.NotAuthorizedException;
Expand Down Expand Up @@ -369,7 +370,7 @@ protected Response post(Response.Status expectedStatus, Form formData, URL url)
* @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
Expand All @@ -382,14 +383,22 @@ protected Response upload(Response.Status expectedStatus, String name, File file
}
}

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.
*
* @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
Expand All @@ -409,7 +418,7 @@ protected Response upload(Response.Status expectedStatus, String name, File file
* @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
Expand Down
38 changes: 23 additions & 15 deletions src/main/java/org/gitlab4j/api/GitLabApiClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.URL;
import java.security.GeneralSecurityException;
Expand All @@ -12,7 +13,6 @@
import java.util.Map;
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;
Expand All @@ -29,7 +29,6 @@
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;
Expand All @@ -38,11 +37,13 @@
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;


/**
Expand Down Expand Up @@ -560,14 +561,13 @@ protected Response post(StreamingOutput stream, String mediaType, Object... path
*
* @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);
}

/**
Expand All @@ -576,7 +576,7 @@ protected Response upload(String name, File fileToUpload, String mediaTypeString
*
* @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
Expand All @@ -593,30 +593,38 @@ protected Response upload(String name, File fileToUpload, String mediaTypeString
*
* @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));
}
Expand Down
21 changes: 18 additions & 3 deletions src/main/java/org/gitlab4j/api/ProjectApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -32,12 +33,10 @@
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;
Expand Down Expand Up @@ -2553,7 +2552,7 @@ public FileUpload uploadFile(Object projectIdOrPath, File fileToUpload) throws G
*
* @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
*/
Expand All @@ -2562,6 +2561,22 @@ public FileUpload uploadFile(Object projectIdOrPath, File fileToUpload, String m
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.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
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;
Expand All @@ -18,17 +22,17 @@

/**
* 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");
Expand All @@ -37,7 +41,7 @@ public class TestFileUpload extends AbstractIntegrationTest {

private static GitLabApi gitLabApi;

public TestFileUpload() {
public TestUpload() {
super();
}

Expand Down Expand Up @@ -93,4 +97,21 @@ public void testFileUploadWithProxy() throws GitLabApiException {

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));
}

}