From 3339609b96a68991a6fa84a6101fa4d7af2250e8 Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Wed, 5 Aug 2020 11:05:19 +0200 Subject: [PATCH] MultipartFormDataRequest - Remove dependencies httpclient and httpmime - It is no longer required to create ContentFile instances --- README.md | 15 +-- pom.xml | 12 +-- .../de/studiocode/gofile4j/ContentFile.java | 33 +++---- .../java/de/studiocode/gofile4j/GoFile4j.java | 54 +++++------ .../request/MultipartFormDataRequest.java | 92 +++++++++++++++++++ .../gofile4j/utils/StringUtils.java | 18 ++++ 6 files changed, 151 insertions(+), 73 deletions(-) create mode 100644 src/main/java/de/studiocode/gofile4j/request/MultipartFormDataRequest.java create mode 100644 src/main/java/de/studiocode/gofile4j/utils/StringUtils.java diff --git a/README.md b/README.md index 1b50d24..da34c3d 100644 --- a/README.md +++ b/README.md @@ -6,20 +6,9 @@ A java wrapper for the API ## Uploading files -### A quick way to upload files +Create a new instance of GoFile4j and provide the Files you want to upload ```java -GoFile4j.uploadFiles(new File("filename.txt"), new File("filename1.txt")); -``` - -### Normal way to upload files -Create a ContentFile - a file and the corresponding content type (example: image.png would be ```ContentType.IMAGE_PNG```) -The right content type is not necessary for the upload to work. However, images for example won't have a preview on the download page if they don't have the right content type. -```java -ContentFile file = new ContentFile(new File("filename.txt"), ContentType.TEXT_PLAIN); -``` -Create a new instance of GoFile4j and provide the ContentFiles you want to upload -```java -GoFile4j goFile4j = new GoFile4j(file); +GoFile4j goFile4j = new GoFile4j(file, file1); ``` optional: set these values ```java diff --git a/pom.xml b/pom.xml index b0a7b08..3683a15 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.studiocode GoFile4j - 1.0-SNAPSHOT + 1.1 @@ -20,16 +20,6 @@ - - org.apache.httpcomponents - httpclient - 4.5.12 - - - org.apache.httpcomponents - httpmime - 4.5.12 - com.google.code.gson gson diff --git a/src/main/java/de/studiocode/gofile4j/ContentFile.java b/src/main/java/de/studiocode/gofile4j/ContentFile.java index 27fc755..aa36160 100644 --- a/src/main/java/de/studiocode/gofile4j/ContentFile.java +++ b/src/main/java/de/studiocode/gofile4j/ContentFile.java @@ -1,42 +1,43 @@ package de.studiocode.gofile4j; -import org.apache.http.entity.ContentType; - import java.io.File; +import java.net.URLConnection; /** - * A class for a file and the corresponding content type (example: image.png would be ContentType.IMAGE_PNG) + * A class for a file and the corresponding content type * The right content type is not necessary for the upload to work. However, images for example won't have a preview on the download page if they don't have the right content type. */ public class ContentFile { - - private ContentType contentType; - private File file; + + private final File file; + private final String contentType; /** - * Create an instance of ContentFile without specifying the content type. Default value: DEFAULT_BINARY (APPLICATION_OCTET_STREAM) + * Create an instance of ContentFile without specifying the content type. The content type will be guessed using URLConnection.guessContentTypeFromName + * * @param file The file */ - public ContentFile(File file) { + public ContentFile(File file) { this.file = file; - this.contentType = ContentType.DEFAULT_BINARY; + this.contentType = URLConnection.guessContentTypeFromName(file.getName()); } /** * Create an instance of ContentFile - * @param file The file + * + * @param file The file * @param contentType The content type */ - public ContentFile(File file, ContentType contentType) { - this(file); + public ContentFile(File file, String contentType) { + this.file = file; this.contentType = contentType; } - public ContentType getContentType() { - return contentType; - } - public File getFile() { return file; } + + public String getContentType() { + return contentType; + } } diff --git a/src/main/java/de/studiocode/gofile4j/GoFile4j.java b/src/main/java/de/studiocode/gofile4j/GoFile4j.java index 63f56ca..1c8b234 100644 --- a/src/main/java/de/studiocode/gofile4j/GoFile4j.java +++ b/src/main/java/de/studiocode/gofile4j/GoFile4j.java @@ -1,16 +1,14 @@ package de.studiocode.gofile4j; +import de.studiocode.gofile4j.request.MultipartFormDataRequest; import de.studiocode.gofile4j.response.FileUploadResponse; import de.studiocode.gofile4j.response.FindServerResponse; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.HttpClients; import java.io.File; import java.io.IOException; -import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.Arrays; /** @@ -31,23 +29,17 @@ public class GoFile4j { private final ContentFile[] files; private final String fileServer; - private final HttpPost postReq; + private final MultipartFormDataRequest request; public GoFile4j(ContentFile... files) throws IOException { this.files = files; - fileServer = getFileServer(); - this.postReq = new HttpPost(UPLOAD_URL_FORMAT.format(fileServer)); + this.fileServer = getFileServer(); + this.request = new MultipartFormDataRequest(UPLOAD_URL_FORMAT.format(fileServer), StandardCharsets.UTF_8); } - - /** - * A quick method to upload files - * - * @param files The files to upload - * @return The file upload result - */ - public static FileUploadResult uploadFiles(File... files) throws IOException { - return new GoFile4j(Arrays.stream(files).map(ContentFile::new).toArray(ContentFile[]::new)).upload(); + + public GoFile4j(File... files) throws IOException { + this(Arrays.stream(files).map(ContentFile::new).toArray(ContentFile[]::new)); } /** @@ -56,9 +48,8 @@ public static FileUploadResult uploadFiles(File... files) throws IOException { * @return The name of the best server available to receive uploads */ private String getFileServer() throws IOException { - HttpGet getReq = new HttpGet(FIND_SERVER_URL); - InputStream in = HttpClients.createDefault().execute(getReq).getEntity().getContent(); - return new FindServerResponse(in).getServer(); + HttpURLConnection findServer = (HttpURLConnection) new URL(FIND_SERVER_URL).openConnection(); + return new FindServerResponse(findServer.getInputStream()).getServer(); } /** @@ -67,21 +58,18 @@ private String getFileServer() throws IOException { * @return The file upload result */ public FileUploadResult upload() throws IOException { - MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + if (email != null) request.addFormField("email", email); + if (description != null) request.addFormField("description", description); + if (password != null) request.addFormField("password", password); + if (tags != null) request.addFormField("tags", tags); + if (expire != null) request.addFormField("expire", expire); + for (ContentFile file : files) { File f = file.getFile(); - builder.addBinaryBody("filesUploaded", f, file.getContentType(), f.getName()); + request.addFormFile("filesUploaded", f, f.getName(), file.getContentType()); } - if (email != null) builder.addTextBody("email", email); - if (description != null) builder.addTextBody("description", description); - if (password != null) builder.addTextBody("password", password); - if (tags != null) builder.addTextBody("tags", tags); - if (expire != null) builder.addTextBody("expire", expire); - HttpEntity multipart = builder.build(); - postReq.setEntity(multipart); - - InputStream content = HttpClients.createDefault().execute(postReq).getEntity().getContent(); - FileUploadResponse response = new FileUploadResponse(content); + + FileUploadResponse response = new FileUploadResponse(request.complete()); return new FileUploadResult(response); } diff --git a/src/main/java/de/studiocode/gofile4j/request/MultipartFormDataRequest.java b/src/main/java/de/studiocode/gofile4j/request/MultipartFormDataRequest.java new file mode 100644 index 0000000..f1e16e3 --- /dev/null +++ b/src/main/java/de/studiocode/gofile4j/request/MultipartFormDataRequest.java @@ -0,0 +1,92 @@ +package de.studiocode.gofile4j.request; + +import de.studiocode.gofile4j.utils.StringUtils; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +public class MultipartFormDataRequest { + + private final String boundary = StringUtils.randomString(25, StringUtils.ALPHABET); + private final Charset charset; + private final HttpURLConnection connection; + private final OutputStream out; + private final PrintWriter writer; + + public MultipartFormDataRequest(String requestUrl, Charset charset) throws IOException { + this.charset = charset; + connection = (HttpURLConnection) new URL(requestUrl).openConnection(); + connection.setDoOutput(true); + connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); + + out = connection.getOutputStream(); + writer = new PrintWriter(new OutputStreamWriter(out, charset)); + } + + public void addHeaderField(String name, String value) { + writer.println(name + ": " + value); + writer.flush(); + } + + public void addFormField(String name, String value) { + writer.println("--" + boundary); + writer.println("Content-Disposition: form-data; name=" + name); + writer.println("Content-Type: text/plain; charset=" + charset.toString()); + writer.println(); + writer.println(value); + writer.flush(); + } + + public void addFormFile(String fieldName, File file, String fileName, String contentType) throws IOException { + writer.println("--" + boundary); + writer.println("Content-Disposition: form-data; name=" + fieldName + "; filename=" + fileName); + writer.println("Content-Type: " + contentType); + writer.println("Content-Transfer-Encoding: binary"); + writer.println(); + writer.flush(); + + InputStream in = new FileInputStream(file); + copy(in, out); + out.flush(); + in.close(); + + writer.println(); + writer.flush(); + } + + public InputStream complete() throws IOException { + writer.flush(); + writer.println("--" + boundary + "--"); + writer.close(); + + int responseCode = connection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + return connection.getInputStream(); + } else throw new IOException("Server responded with non-OK status: " + responseCode); + } + + public List completeToStringList() throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(complete(), charset)); + + List lines = new ArrayList<>(); + String line; + while ((line = reader.readLine()) != null) { + lines.add(line); + } + + return lines; + } + + private void copy(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[8192]; + int length; + while ((length = in.read(buffer)) != -1) { + out.write(buffer, 0, length); + } + } + +} diff --git a/src/main/java/de/studiocode/gofile4j/utils/StringUtils.java b/src/main/java/de/studiocode/gofile4j/utils/StringUtils.java new file mode 100644 index 0000000..856f22c --- /dev/null +++ b/src/main/java/de/studiocode/gofile4j/utils/StringUtils.java @@ -0,0 +1,18 @@ +package de.studiocode.gofile4j.utils; + +import java.util.Random; + +public class StringUtils { + + public static final String ALPHABET = "abcedfghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private static final Random RANDOM = new Random(); + + public static String randomString(int length, String letters) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i != length; i++) { + builder.append(letters.charAt(RANDOM.nextInt(letters.length()))); + } + return builder.toString(); + } + +}