Skip to content

Commit c0d17ed

Browse files
authored
Merge pull request #776 from alb-i986/upload-InputStream
Upload: accept an InputStream besides a File
2 parents 15fc264 + 1a1c3b2 commit c0d17ed

File tree

4 files changed

+79
-26
lines changed

4 files changed

+79
-26
lines changed

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

Lines changed: 12 additions & 3 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;
@@ -369,7 +370,7 @@ protected Response post(Response.Status expectedStatus, Form formData, URL url)
369370
* @param expectedStatus the HTTP status that should be returned from the server
370371
* @param name the name for the form field that contains the file name
371372
* @param fileToUpload a File instance pointing to the file to upload
372-
* @param mediaType the content-type of the uploaded file, if null will be determined from fileToUpload
373+
* @param mediaType unused; will be removed in the next major version
373374
* @param pathArgs variable list of arguments used to build the URI
374375
* @return a ClientResponse instance with the data returned from the endpoint
375376
* @throws GitLabApiException if any exception occurs during execution
@@ -382,14 +383,22 @@ 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.
388397
*
389398
* @param expectedStatus the HTTP status that should be returned from the server
390399
* @param name the name for the form field that contains the file name
391400
* @param fileToUpload a File instance pointing to the file to upload
392-
* @param mediaType the content-type of the uploaded file, if null will be determined from fileToUpload
401+
* @param mediaType unused; will be removed in the next major version
393402
* @param url the fully formed path to the GitLab API endpoint
394403
* @return a ClientResponse instance with the data returned from the endpoint
395404
* @throws GitLabApiException if any exception occurs during execution
@@ -409,7 +418,7 @@ protected Response upload(Response.Status expectedStatus, String name, File file
409418
* @param expectedStatus the HTTP status that should be returned from the server
410419
* @param name the name for the form field that contains the file name
411420
* @param fileToUpload a File instance pointing to the file to upload
412-
* @param mediaType the content-type of the uploaded file, if null will be determined from fileToUpload
421+
* @param mediaType unused; will be removed in the next major version
413422
* @param formData the Form containing the name/value pairs
414423
* @param url the fully formed path to the GitLab API endpoint
415424
* @return a ClientResponse instance with the data returned from the endpoint

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

Lines changed: 23 additions & 15 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;
@@ -13,7 +14,6 @@
1314
import java.util.function.Supplier;
1415
import java.util.logging.Level;
1516
import java.util.logging.Logger;
16-
1717
import javax.net.ssl.HostnameVerifier;
1818
import javax.net.ssl.SSLContext;
1919
import javax.net.ssl.SSLEngine;
@@ -30,7 +30,6 @@
3030
import javax.ws.rs.core.MultivaluedMap;
3131
import javax.ws.rs.core.Response;
3232
import javax.ws.rs.core.StreamingOutput;
33-
3433
import org.gitlab4j.api.Constants.TokenType;
3534
import org.gitlab4j.api.GitLabApi.ApiVersion;
3635
import org.gitlab4j.api.utils.JacksonJson;
@@ -39,11 +38,13 @@
3938
import org.glassfish.jersey.client.ClientConfig;
4039
import org.glassfish.jersey.client.ClientProperties;
4140
import org.glassfish.jersey.client.JerseyClientBuilder;
41+
import org.glassfish.jersey.media.multipart.BodyPart;
4242
import org.glassfish.jersey.media.multipart.Boundary;
4343
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
4444
import org.glassfish.jersey.media.multipart.MultiPart;
4545
import org.glassfish.jersey.media.multipart.MultiPartFeature;
4646
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
47+
import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
4748

4849

4950
/**
@@ -561,14 +562,13 @@ protected Response post(StreamingOutput stream, String mediaType, Object... path
561562
*
562563
* @param name the name for the form field that contains the file name
563564
* @param fileToUpload a File instance pointing to the file to upload
564-
* @param mediaTypeString the content-type of the uploaded file, if null will be determined from fileToUpload
565+
* @param mediaTypeString unused; will be removed in the next major version
565566
* @param pathArgs variable list of arguments used to build the URI
566567
* @return a ClientResponse instance with the data returned from the endpoint
567568
* @throws IOException if an error occurs while constructing the URL
568569
*/
569570
protected Response upload(String name, File fileToUpload, String mediaTypeString, Object... pathArgs) throws IOException {
570-
URL url = getApiUrl(pathArgs);
571-
return (upload(name, fileToUpload, mediaTypeString, null, url));
571+
return upload(name, fileToUpload, mediaTypeString, null, pathArgs);
572572
}
573573

574574
/**
@@ -577,7 +577,7 @@ protected Response upload(String name, File fileToUpload, String mediaTypeString
577577
*
578578
* @param name the name for the form field that contains the file name
579579
* @param fileToUpload a File instance pointing to the file to upload
580-
* @param mediaTypeString the content-type of the uploaded file, if null will be determined from fileToUpload
580+
* @param mediaTypeString unused; will be removed in the next major version
581581
* @param formData the Form containing the name/value pairs
582582
* @param pathArgs variable list of arguments used to build the URI
583583
* @return a ClientResponse instance with the data returned from the endpoint
@@ -594,30 +594,38 @@ protected Response upload(String name, File fileToUpload, String mediaTypeString
594594
*
595595
* @param name the name for the form field that contains the file name
596596
* @param fileToUpload a File instance pointing to the file to upload
597-
* @param mediaTypeString the content-type of the uploaded file, if null will be determined from fileToUpload
597+
* @param mediaTypeString unused; will be removed in the next major version
598598
* @param formData the Form containing the name/value pairs
599599
* @param url the fully formed path to the GitLab API endpoint
600600
* @return a ClientResponse instance with the data returned from the endpoint
601601
* @throws IOException if an error occurs while constructing the URL
602602
*/
603603
protected Response upload(String name, File fileToUpload, String mediaTypeString, Form formData, URL url) throws IOException {
604+
FileDataBodyPart filePart = new FileDataBodyPart(name, fileToUpload);
605+
return upload(filePart, formData, url);
606+
}
604607

605-
MediaType mediaType = (mediaTypeString != null ? MediaType.valueOf(mediaTypeString) : null);
606-
try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
608+
protected Response upload(String name, InputStream inputStream, String filename, String mediaTypeString, Object... pathArgs) throws IOException {
609+
URL url = getApiUrl(pathArgs);
610+
return (upload(name, inputStream, filename, mediaTypeString, null, url));
611+
}
607612

613+
protected Response upload(String name, InputStream inputStream, String filename, String mediaTypeString, Form formData, URL url) throws IOException {
614+
StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart(name, inputStream, filename);
615+
return upload(streamDataBodyPart, formData, url);
616+
}
617+
618+
protected Response upload(BodyPart bodyPart, Form formData, URL url) throws IOException {
619+
try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
608620
if (formData != null) {
609-
MultivaluedMap<String, String> formParams = formData.asMap();
610-
formParams.forEach((key, values) -> {
621+
formData.asMap().forEach((key, values) -> {
611622
if (values != null) {
612623
values.forEach(value -> multiPart.field(key, value));
613624
}
614625
});
615626
}
616627

617-
FileDataBodyPart filePart = mediaType != null ?
618-
new FileDataBodyPart(name, fileToUpload, mediaType) :
619-
new FileDataBodyPart(name, fileToUpload);
620-
multiPart.bodyPart(filePart);
628+
multiPart.bodyPart(bodyPart);
621629
final Entity<?> entity = Entity.entity(multiPart, Boundary.addBoundary(multiPart.getMediaType()));
622630
return (invocation(url, null).post(entity));
623631
}

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

Lines changed: 18 additions & 3 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;
@@ -2565,7 +2564,7 @@ public FileUpload uploadFile(Object projectIdOrPath, File fileToUpload) throws G
25652564
*
25662565
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required
25672566
* @param fileToUpload the File instance of the file to upload, required
2568-
* @param mediaType the media type of the file to upload, optional
2567+
* @param mediaType unused; will be removed in the next major version
25692568
* @return a FileUpload instance with information on the just uploaded file
25702569
* @throws GitLabApiException if any exception occurs
25712570
*/
@@ -2574,6 +2573,22 @@ public FileUpload uploadFile(Object projectIdOrPath, File fileToUpload, String m
25742573
return (response.readEntity(FileUpload.class));
25752574
}
25762575

2576+
/**
2577+
* Uploads some data in an {@link InputStream} to the specified project,
2578+
* to be used in an issue or merge request description, or a comment.
2579+
*
2580+
* <pre><code>GitLab Endpoint: POST /projects/:id/uploads</code></pre>
2581+
*
2582+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required
2583+
* @param inputStream the data to upload, required
2584+
* @return a FileUpload instance with information on the just uploaded file
2585+
* @throws GitLabApiException if any exception occurs
2586+
*/
2587+
public FileUpload uploadFile(Object projectIdOrPath, InputStream inputStream, String filename, String mediaType) throws GitLabApiException {
2588+
Response response = upload(Response.Status.CREATED, "file", inputStream, filename, mediaType, "projects", getProjectIdOrPath(projectIdOrPath), "uploads");
2589+
return (response.readEntity(FileUpload.class));
2590+
}
2591+
25772592
/**
25782593
* Get the project's push rules.
25792594
*

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)