Skip to content

Commit 115a6a8

Browse files
committed
Upload: accept an InputStream besides a File
This makes it possible to stream data coming from another server straight into the POST request to Gitlab, saving an extra, expensive, and useless IO operation on disk.
1 parent 37617ec commit 115a6a8

File tree

4 files changed

+78
-18
lines changed

4 files changed

+78
-18
lines changed

src/main/java/org/gitlab4j/api/AbstractApi.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.gitlab4j.api;
22

33
import java.io.File;
4+
import java.io.InputStream;
45
import java.net.URL;
56

67
import javax.ws.rs.NotAuthorizedException;
@@ -382,6 +383,14 @@ protected Response upload(Response.Status expectedStatus, String name, File file
382383
}
383384
}
384385

386+
protected Response upload(Response.Status expectedStatus, String name, InputStream inputStream, String filename, String mediaType, Object... pathArgs) throws GitLabApiException {
387+
try {
388+
return validate(getApiClient().upload(name, inputStream, filename, mediaType, pathArgs), expectedStatus);
389+
} catch (Exception e) {
390+
throw handle(e);
391+
}
392+
}
393+
385394
/**
386395
* Perform a file upload with the specified File instance and path objects, returning
387396
* a ClientResponse instance with the data returned from the endpoint.

src/main/java/org/gitlab4j/api/GitLabApiClient.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.File;
44
import java.io.IOException;
5+
import java.io.InputStream;
56
import java.net.Socket;
67
import java.net.URL;
78
import java.security.GeneralSecurityException;
@@ -12,7 +13,6 @@
1213
import java.util.Map;
1314
import java.util.logging.Level;
1415
import java.util.logging.Logger;
15-
1616
import javax.net.ssl.HostnameVerifier;
1717
import javax.net.ssl.SSLContext;
1818
import javax.net.ssl.SSLEngine;
@@ -29,7 +29,6 @@
2929
import javax.ws.rs.core.MultivaluedMap;
3030
import javax.ws.rs.core.Response;
3131
import javax.ws.rs.core.StreamingOutput;
32-
3332
import org.gitlab4j.api.Constants.TokenType;
3433
import org.gitlab4j.api.GitLabApi.ApiVersion;
3534
import org.gitlab4j.api.utils.JacksonJson;
@@ -38,11 +37,13 @@
3837
import org.glassfish.jersey.client.ClientConfig;
3938
import org.glassfish.jersey.client.ClientProperties;
4039
import org.glassfish.jersey.client.JerseyClientBuilder;
40+
import org.glassfish.jersey.media.multipart.BodyPart;
4141
import org.glassfish.jersey.media.multipart.Boundary;
4242
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
4343
import org.glassfish.jersey.media.multipart.MultiPart;
4444
import org.glassfish.jersey.media.multipart.MultiPartFeature;
4545
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
46+
import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
4647

4748

4849
/**
@@ -566,8 +567,7 @@ protected Response post(StreamingOutput stream, String mediaType, Object... path
566567
* @throws IOException if an error occurs while constructing the URL
567568
*/
568569
protected Response upload(String name, File fileToUpload, String mediaTypeString, Object... pathArgs) throws IOException {
569-
URL url = getApiUrl(pathArgs);
570-
return (upload(name, fileToUpload, mediaTypeString, null, url));
570+
return upload(name, fileToUpload, mediaTypeString, null, pathArgs);
571571
}
572572

573573
/**
@@ -600,23 +600,37 @@ protected Response upload(String name, File fileToUpload, String mediaTypeString
600600
* @throws IOException if an error occurs while constructing the URL
601601
*/
602602
protected Response upload(String name, File fileToUpload, String mediaTypeString, Form formData, URL url) throws IOException {
603+
MediaType mediaType = (mediaTypeString != null ? MediaType.valueOf(mediaTypeString) : null);
604+
FileDataBodyPart filePart = mediaType != null ?
605+
new FileDataBodyPart(name, fileToUpload, mediaType) :
606+
new FileDataBodyPart(name, fileToUpload);
607+
return upload(filePart, formData, url);
608+
}
603609

610+
protected Response upload(String name, InputStream inputStream, String filename, String mediaTypeString, Object... pathArgs) throws IOException {
611+
URL url = getApiUrl(pathArgs);
612+
return (upload(name, inputStream, filename, mediaTypeString, null, url));
613+
}
614+
615+
protected Response upload(String name, InputStream inputStream, String filename, String mediaTypeString, Form formData, URL url) throws IOException {
604616
MediaType mediaType = (mediaTypeString != null ? MediaType.valueOf(mediaTypeString) : null);
605-
try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
617+
StreamDataBodyPart streamDataBodyPart = mediaType != null ?
618+
new StreamDataBodyPart(name, inputStream, filename, mediaType) :
619+
new StreamDataBodyPart(name, inputStream, filename);
620+
return upload(streamDataBodyPart, formData, url);
621+
}
606622

623+
protected Response upload(BodyPart bodyPart, Form formData, URL url) throws IOException {
624+
try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
607625
if (formData != null) {
608-
MultivaluedMap<String, String> formParams = formData.asMap();
609-
formParams.forEach((key, values) -> {
626+
formData.asMap().forEach((key, values) -> {
610627
if (values != null) {
611628
values.forEach(value -> multiPart.field(key, value));
612629
}
613630
});
614631
}
615632

616-
FileDataBodyPart filePart = mediaType != null ?
617-
new FileDataBodyPart(name, fileToUpload, mediaType) :
618-
new FileDataBodyPart(name, fileToUpload);
619-
multiPart.bodyPart(filePart);
633+
multiPart.bodyPart(bodyPart);
620634
final Entity<?> entity = Entity.entity(multiPart, Boundary.addBoundary(multiPart.getMediaType()));
621635
return (invocation(url, null).post(entity));
622636
}

src/main/java/org/gitlab4j/api/ProjectApi.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
package org.gitlab4j.api;
2525

2626
import java.io.File;
27+
import java.io.InputStream;
2728
import java.io.UnsupportedEncodingException;
2829
import java.net.URLEncoder;
2930
import java.util.Date;
@@ -32,12 +33,10 @@
3233
import java.util.Objects;
3334
import java.util.Optional;
3435
import java.util.stream.Stream;
35-
3636
import javax.ws.rs.core.Form;
3737
import javax.ws.rs.core.GenericType;
3838
import javax.ws.rs.core.MultivaluedMap;
3939
import javax.ws.rs.core.Response;
40-
4140
import org.gitlab4j.api.GitLabApi.ApiVersion;
4241
import org.gitlab4j.api.models.AccessLevel;
4342
import org.gitlab4j.api.models.AccessRequest;
@@ -2562,6 +2561,23 @@ public FileUpload uploadFile(Object projectIdOrPath, File fileToUpload, String m
25622561
return (response.readEntity(FileUpload.class));
25632562
}
25642563

2564+
/**
2565+
* Uploads some data in an {@link InputStream} to the specified project,
2566+
* to be used in an issue or merge request description, or a comment.
2567+
*
2568+
* <pre><code>GitLab Endpoint: POST /projects/:id/uploads</code></pre>
2569+
*
2570+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required
2571+
* @param inputStream the data to upload, required
2572+
* @param mediaType the media type of the file to upload, required
2573+
* @return a FileUpload instance with information on the just uploaded file
2574+
* @throws GitLabApiException if any exception occurs
2575+
*/
2576+
public FileUpload uploadFile(Object projectIdOrPath, InputStream inputStream, String filename, String mediaType) throws GitLabApiException {
2577+
Response response = upload(Response.Status.CREATED, "file", inputStream, filename, mediaType, "projects", getProjectIdOrPath(projectIdOrPath), "uploads");
2578+
return (response.readEntity(FileUpload.class));
2579+
}
2580+
25652581
/**
25662582
* Get the project's push rules.
25672583
*

src/test/java/org/gitlab4j/api/TestFileUpload.java renamed to src/test/java/org/gitlab4j/api/TestUpload.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package org.gitlab4j.api;
22

3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.endsWith;
5+
import static org.hamcrest.Matchers.equalTo;
36
import static org.junit.Assert.assertNotNull;
47
import static org.junit.Assume.assumeNotNull;
58
import static org.junit.Assume.assumeTrue;
69

710
import java.io.File;
11+
import java.io.FileInputStream;
12+
import java.io.FileNotFoundException;
813
import java.util.Map;
9-
1014
import org.gitlab4j.api.models.FileUpload;
1115
import org.gitlab4j.api.models.Project;
1216
import org.junit.Before;
@@ -18,17 +22,17 @@
1822

1923
/**
2024
* In order for these tests to run you must set the following properties in test-gitlab4j.properties
21-
*
25+
*
2226
* TEST_NAMESPACE
2327
* TEST_PROJECT_NAME
2428
* TEST_HOST_URL
2529
* TEST_PRIVATE_TOKEN
26-
*
30+
*
2731
* If any of the above are NULL, all tests in this class will be skipped.
2832
*/
2933
@Category(IntegrationTest.class)
3034
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
31-
public class TestFileUpload extends AbstractIntegrationTest {
35+
public class TestUpload extends AbstractIntegrationTest {
3236

3337
// The following needs to be set to your test repository
3438
private static final String TEST_PROXY_URI = HelperUtils.getProperty("TEST_PROXY_URI");
@@ -37,7 +41,7 @@ public class TestFileUpload extends AbstractIntegrationTest {
3741

3842
private static GitLabApi gitLabApi;
3943

40-
public TestFileUpload() {
44+
public TestUpload() {
4145
super();
4246
}
4347

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

9498
gitLabApi.close();
9599
}
100+
101+
@Test
102+
public void testInputStreamUpload() throws GitLabApiException, FileNotFoundException {
103+
104+
Project project = gitLabApi.getProjectApi().getProject(TEST_NAMESPACE, TEST_PROJECT_NAME);
105+
assertNotNull(project);
106+
107+
String filename = "README.md";
108+
File fileToUpload = new File(filename);
109+
FileUpload fileUpload = gitLabApi.getProjectApi().uploadFile(
110+
project.getId(), new FileInputStream(fileToUpload), filename, null);
111+
112+
assertNotNull(fileUpload);
113+
assertThat(fileUpload.getUrl(), endsWith(filename));
114+
assertThat(fileUpload.getAlt(), equalTo(filename));
115+
}
116+
96117
}

0 commit comments

Comments
 (0)