Skip to content

Commit 8e173b7

Browse files
committed
Add ability to add a dir (only empty works until multiple multipart elements are supported by ipfs.
1 parent ceeb061 commit 8e173b7

File tree

4 files changed

+77
-25
lines changed

4 files changed

+77
-25
lines changed

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import java.io.*;
88
import java.net.*;
9+
import java.nio.file.*;
910
import java.util.*;
1011
import java.util.stream.*;
1112

@@ -73,10 +74,10 @@ public MerkleNode add(NamedStreamable file) throws IOException {
7374
}
7475

7576
public List<MerkleNode> add(List<NamedStreamable> files) throws IOException {
76-
Multipart m = new Multipart("http://" + host + ":" + port + version+"add?stream-channels=true", "UTF-8");
77+
Multipart m = new Multipart("http://" + host + ":" + port + version + "add", "UTF-8");
7778
for (NamedStreamable file: files) {
7879
if (file.isDirectory()) {
79-
m.addSubtree("", ((NamedStreamable.FileWrapper)file).getFile());
80+
m.addSubtree(Paths.get("/"), file);
8081
} else
8182
m.addFilePart("file", file);
8283
};

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

+18-13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.*;
44
import java.net.*;
5+
import java.nio.file.*;
56
import java.util.*;
67

78
public class Multipart {
@@ -52,33 +53,37 @@ public void addFormField(String name, String value) {
5253
writer.flush();
5354
}
5455

55-
public void addSubtree(String path, File dir) throws IOException {
56-
String dirPath = path + (path.length() > 0 ? "/" : "") + dir.getName();
56+
public void addSubtree(Path parentPath, NamedStreamable dir) throws IOException {
57+
Path dirPath = parentPath.resolve(dir.getName().get());
5758
addDirectoryPart(dirPath);
58-
for (File f: dir.listFiles()) {
59+
for (NamedStreamable f: dir.getChildren()) {
5960
if (f.isDirectory())
6061
addSubtree(dirPath, f);
6162
else
62-
addFilePart("file", new NamedStreamable.FileWrapper(dirPath + "/", f));
63+
addFilePart("file", f);
6364
}
6465
}
6566

66-
public void addDirectoryPart(String path) {
67+
public void addDirectoryPart(Path path) {
68+
writer.append("--" + boundary).append(LINE_FEED);
69+
writer.append("Content-Disposition: file; filename=\"" + encode(path.toString()) + "\"").append(LINE_FEED);
70+
writer.append("Content-Type: application/x-directory").append(LINE_FEED);
71+
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
72+
writer.append(LINE_FEED);
73+
writer.append(LINE_FEED);
74+
writer.flush();
75+
}
76+
77+
private static String encode(String in) {
6778
try {
68-
writer.append("--" + boundary).append(LINE_FEED);
69-
writer.append("Content-Disposition: file; filename=\"" + URLEncoder.encode(path, "UTF-8") + "\"").append(LINE_FEED);
70-
writer.append("Content-Type: application/x-directory").append(LINE_FEED);
71-
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
72-
writer.append(LINE_FEED);
73-
writer.append(LINE_FEED);
74-
writer.flush();
79+
return URLEncoder.encode(in, "UTF-8");
7580
} catch (UnsupportedEncodingException e) {
7681
throw new RuntimeException(e);
7782
}
7883
}
7984

8085
public void addFilePart(String fieldName, NamedStreamable uploadFile) {
81-
Optional<String> fileName = uploadFile.getName();
86+
Optional<String> fileName = uploadFile.getName().map(n -> encode(n));
8287
writer.append("--" + boundary).append(LINE_FEED);
8388
if (!fileName.isPresent())
8489
writer.append("Content-Disposition: file; name=\"" + fieldName + "\";").append(LINE_FEED);

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

+48-10
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
import java.io.*;
44
import java.net.*;
55
import java.util.*;
6+
import java.util.stream.*;
67

78
public interface NamedStreamable
89
{
910
InputStream getInputStream() throws IOException;
1011

1112
Optional<String> getName();
1213

14+
List<NamedStreamable> getChildren();
15+
1316
boolean isDirectory();
1417

1518
default byte[] getContents() throws IOException {
@@ -24,15 +27,9 @@ default byte[] getContents() throws IOException {
2427

2528
class FileWrapper implements NamedStreamable {
2629
private final File source;
27-
private final String pathPrefix;
28-
29-
public FileWrapper(String pathPrefix, File source) {
30-
this.source = source;
31-
this.pathPrefix = pathPrefix;
32-
}
3330

3431
public FileWrapper(File source) {
35-
this("", source);
32+
this.source = source;
3633
}
3734

3835
public InputStream getInputStream() throws IOException {
@@ -43,13 +40,18 @@ public boolean isDirectory() {
4340
return source.isDirectory();
4441
}
4542

46-
public File getFile() {
47-
return source;
43+
@Override
44+
public List<NamedStreamable> getChildren() {
45+
return isDirectory() ?
46+
Stream.of(source.listFiles())
47+
.map(NamedStreamable.FileWrapper::new)
48+
.collect(Collectors.toList()) :
49+
Collections.emptyList();
4850
}
4951

5052
public Optional<String> getName() {
5153
try {
52-
return Optional.of(URLEncoder.encode(pathPrefix + source.getName(), "UTF-8"));
54+
return Optional.of(URLEncoder.encode(source.getName(), "UTF-8"));
5355
} catch (UnsupportedEncodingException e) {
5456
throw new RuntimeException(e);
5557
}
@@ -81,8 +83,44 @@ public InputStream getInputStream() throws IOException {
8183
return new ByteArrayInputStream(data);
8284
}
8385

86+
@Override
87+
public List<NamedStreamable> getChildren() {
88+
return Collections.emptyList();
89+
}
90+
8491
public Optional<String> getName() {
8592
return name;
8693
}
8794
}
95+
96+
class DirWrapper implements NamedStreamable {
97+
98+
private final String name;
99+
private final List<NamedStreamable> children;
100+
101+
public DirWrapper(String name, List<NamedStreamable> children) {
102+
this.name = name;
103+
this.children = children;
104+
}
105+
106+
@Override
107+
public InputStream getInputStream() throws IOException {
108+
throw new IllegalStateException("Cannot get an input stream for a directory!");
109+
}
110+
111+
@Override
112+
public Optional<String> getName() {
113+
return Optional.of(name);
114+
}
115+
116+
@Override
117+
public List<NamedStreamable> getChildren() {
118+
return children;
119+
}
120+
121+
@Override
122+
public boolean isDirectory() {
123+
return true;
124+
}
125+
}
88126
}

src/test/java/io/ipfs/api/APITest.java

+8
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ public void singleFileTest() {
8181
fileTest(file);
8282
}
8383

84+
@org.junit.Test
85+
public void dirTest() throws IOException {
86+
NamedStreamable.DirWrapper dir = new NamedStreamable.DirWrapper("root", Arrays.asList());
87+
MerkleNode addResult = ipfs.add(dir);
88+
List<MerkleNode> ls = ipfs.ls(addResult.hash);
89+
Assert.assertTrue(ls.size() > 0);
90+
}
91+
8492
@org.junit.Test
8593
public void directoryTest() throws IOException {
8694
Random rnd = new Random();

0 commit comments

Comments
 (0)