Skip to content

Commit a34599a

Browse files
committed
Improve multipart implementation
1 parent cec4e52 commit a34599a

File tree

2 files changed

+50
-38
lines changed

2 files changed

+50
-38
lines changed

src/main/java/io/ipfs/api/IPFS.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,15 +288,23 @@ public List<MerkleNode> put(List<byte[]> data) throws IOException {
288288

289289
public List<MerkleNode> put(List<byte[]> data, Optional<String> format) throws IOException {
290290
// N.B. Once IPFS implements a bulk put this can become a single multipart call with multiple 'files'
291-
return data.stream().map(array -> put(array, format)).collect(Collectors.toList());
291+
List<MerkleNode> res = new ArrayList<>();
292+
for (byte[] value : data) {
293+
res.add(put(value, format));
294+
}
295+
return res;
292296
}
293297

294-
public MerkleNode put(byte[] data, Optional<String> format) {
298+
public MerkleNode put(byte[] data, Optional<String> format) throws IOException {
295299
String fmt = format.map(f -> "&format=" + f).orElse("");
296300
Multipart m = new Multipart(protocol +"://" + host + ":" + port + version+"block/put?stream-channels=true" + fmt, "UTF-8");
297-
m.addFilePart("file", Paths.get(""), new NamedStreamable.ByteArrayWrapper(data));
298-
String res = m.finish();
299-
return JSONParser.parseStream(res).stream().map(x -> MerkleNode.fromJSON((Map<String, Object>) x)).findFirst().get();
301+
try {
302+
m.addFilePart("file", Paths.get(""), new NamedStreamable.ByteArrayWrapper(data));
303+
String res = m.finish();
304+
return JSONParser.parseStream(res).stream().map(x -> MerkleNode.fromJSON((Map<String, Object>) x)).findFirst().get();
305+
} catch (IOException e) {
306+
throw new RuntimeException(e.getMessage(), e);
307+
}
300308
}
301309

302310
public Map stat(Multihash hash) throws IOException {

src/main/java/io/ipfs/api/Multipart.java

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public class Multipart {
1111
private HttpURLConnection httpConn;
1212
private String charset;
1313
private OutputStream out;
14-
private PrintWriter writer;
1514

1615
public Multipart(String requestURL, String charset) {
1716
this.charset = charset;
@@ -27,7 +26,6 @@ public Multipart(String requestURL, String charset) {
2726
httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
2827
httpConn.setRequestProperty("User-Agent", "Java IPFS CLient");
2928
out = httpConn.getOutputStream();
30-
writer = new PrintWriter(new OutputStreamWriter(out, charset), true);
3129
} catch (IOException e) {
3230
throw new RuntimeException(e.getMessage(), e);
3331
}
@@ -41,15 +39,20 @@ public static String createBoundary() {
4139
b.append(allowed.charAt(r.nextInt(allowed.length())));
4240
return b.toString();
4341
}
42+
43+
private Multipart append(String value) throws IOException {
44+
out.write(value.getBytes(charset));
45+
return this;
46+
}
4447

45-
public void addFormField(String name, String value) {
46-
writer.append("--").append(boundary).append(LINE_FEED);
47-
writer.append("Content-Disposition: form-data; name=\"").append(name).append("\"")
48+
public void addFormField(String name, String value) throws IOException {
49+
append("--").append(boundary).append(LINE_FEED);
50+
append("Content-Disposition: form-data; name=\"").append(name).append("\"")
4851
.append(LINE_FEED);
49-
writer.append("Content-Type: text/plain; charset=").append(charset).append(LINE_FEED);
50-
writer.append(LINE_FEED);
51-
writer.append(value).append(LINE_FEED);
52-
writer.flush();
52+
append("Content-Type: text/plain; charset=").append(charset).append(LINE_FEED);
53+
append(LINE_FEED);
54+
append(value).append(LINE_FEED);
55+
out.flush();
5356
}
5457

5558
public void addSubtree(Path parentPath, NamedStreamable dir) throws IOException {
@@ -63,14 +66,14 @@ public void addSubtree(Path parentPath, NamedStreamable dir) throws IOException
6366
}
6467
}
6568

66-
public void addDirectoryPart(Path path) {
67-
writer.append("--").append(boundary).append(LINE_FEED);
68-
writer.append("Content-Disposition: file; filename=\"").append(encode(path.toString())).append("\"").append(LINE_FEED);
69-
writer.append("Content-Type: application/x-directory").append(LINE_FEED);
70-
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
71-
writer.append(LINE_FEED);
72-
writer.append(LINE_FEED);
73-
writer.flush();
69+
public void addDirectoryPart(Path path) throws IOException {
70+
append("--").append(boundary).append(LINE_FEED);
71+
append("Content-Disposition: file; filename=\"").append(encode(path.toString())).append("\"").append(LINE_FEED);
72+
append("Content-Type: application/x-directory").append(LINE_FEED);
73+
append("Content-Transfer-Encoding: binary").append(LINE_FEED);
74+
append(LINE_FEED);
75+
append(LINE_FEED);
76+
out.flush();
7477
}
7578

7679
private static String encode(String in) {
@@ -81,17 +84,17 @@ private static String encode(String in) {
8184
}
8285
}
8386

84-
public void addFilePart(String fieldName, Path parent, NamedStreamable uploadFile) {
87+
public void addFilePart(String fieldName, Path parent, NamedStreamable uploadFile) throws IOException {
8588
Optional<String> fileName = uploadFile.getName().map(n -> encode(parent.resolve(n).toString().replace('\\','/')));
86-
writer.append("--").append(boundary).append(LINE_FEED);
89+
append("--").append(boundary).append(LINE_FEED);
8790
if (!fileName.isPresent())
88-
writer.append("Content-Disposition: file; name=\"").append(fieldName).append("\";").append(LINE_FEED);
91+
append("Content-Disposition: file; name=\"").append(fieldName).append("\";").append(LINE_FEED);
8992
else
90-
writer.append("Content-Disposition: file; filename=\"").append(fileName.get()).append("\";").append(LINE_FEED);
91-
writer.append("Content-Type: application/octet-stream").append(LINE_FEED);
92-
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
93-
writer.append(LINE_FEED);
94-
writer.flush();
93+
append("Content-Disposition: file; filename=\"").append(fileName.get()).append("\";").append(LINE_FEED);
94+
append("Content-Type: application/octet-stream").append(LINE_FEED);
95+
append("Content-Transfer-Encoding: binary").append(LINE_FEED);
96+
append(LINE_FEED);
97+
out.flush();
9598

9699
try {
97100
InputStream inputStream = uploadFile.getInputStream();
@@ -105,20 +108,21 @@ public void addFilePart(String fieldName, Path parent, NamedStreamable uploadFil
105108
throw new RuntimeException(e.getMessage(), e);
106109
}
107110

108-
writer.append(LINE_FEED);
109-
writer.flush();
111+
append(LINE_FEED);
112+
out.flush();
110113
}
111114

112-
public void addHeaderField(String name, String value) {
113-
writer.append(name + ": " + value).append(LINE_FEED);
114-
writer.flush();
115+
public void addHeaderField(String name, String value) throws IOException {
116+
append(name + ": " + value).append(LINE_FEED);
117+
out.flush();
115118
}
116119

117-
public String finish() {
120+
public String finish() throws IOException {
118121
StringBuilder b = new StringBuilder();
119122

120-
writer.append("--" + boundary + "--").append(LINE_FEED);
121-
writer.close();
123+
append("--" + boundary + "--").append(LINE_FEED);
124+
out.flush();
125+
out.close();
122126

123127
try {
124128
int status = httpConn.getResponseCode();

0 commit comments

Comments
 (0)