Skip to content

Commit 259e78b

Browse files
committed
Update ParseFileController to save file
1 parent c7554b9 commit 259e78b

File tree

3 files changed

+103
-5
lines changed

3 files changed

+103
-5
lines changed

Parse/src/main/java/com/parse/ParseFileController.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,53 @@ public ParseFile.State then(Task<JSONObject> task) throws Exception {
117117
}, Task.BACKGROUND_EXECUTOR);
118118
}
119119

120+
public Task<ParseFile.State> saveAsync(
121+
final ParseFile.State state,
122+
final File file,
123+
String sessionToken,
124+
ProgressCallback uploadProgressCallback,
125+
Task<Void> cancellationToken) {
126+
if (state.url() != null) { // !isDirty
127+
return Task.forResult(state);
128+
}
129+
if (cancellationToken != null && cancellationToken.isCancelled()) {
130+
return Task.cancelled();
131+
}
132+
133+
final ParseRESTCommand command = new ParseRESTFileCommand.Builder()
134+
.fileName(state.name())
135+
.file(file)
136+
.contentType(state.mimeType())
137+
.sessionToken(sessionToken)
138+
.build();
139+
command.enableRetrying();
140+
141+
return command.executeAsync(
142+
restClient,
143+
uploadProgressCallback,
144+
null,
145+
cancellationToken
146+
).onSuccess(new Continuation<JSONObject, ParseFile.State>() {
147+
@Override
148+
public ParseFile.State then(Task<JSONObject> task) throws Exception {
149+
JSONObject result = task.getResult();
150+
ParseFile.State newState = new ParseFile.State.Builder(state)
151+
.name(result.getString("name"))
152+
.url(result.getString("url"))
153+
.build();
154+
155+
// Write data to cache
156+
try {
157+
ParseFileUtils.copyFile(file, getCacheFile(newState));
158+
} catch (IOException e) {
159+
// do nothing
160+
}
161+
162+
return newState;
163+
}
164+
}, Task.BACKGROUND_EXECUTOR);
165+
}
166+
120167
public Task<File> fetchAsync(
121168
final ParseFile.State state,
122169
@SuppressWarnings("UnusedParameters") String sessionToken,

Parse/src/main/java/com/parse/ParseRESTFileCommand.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@
1111
/**
1212
* REST network command for creating & uploading {@link ParseFile}s.
1313
*/
14+
15+
import java.io.File;
16+
1417
/** package */ class ParseRESTFileCommand extends ParseRESTCommand {
1518

1619
public static class Builder extends Init<Builder> {
1720

1821
private byte[] data = null;
1922
private String contentType = null;
23+
private File file;
2024

2125
public Builder() {
2226
// We only ever use ParseRESTFileCommand for file uploads, so default to POST.
@@ -37,6 +41,11 @@ public Builder contentType(String contentType) {
3741
return this;
3842
}
3943

44+
public Builder file(File file) {
45+
this.file = file;
46+
return this;
47+
}
48+
4049
@Override
4150
/* package */ Builder self() {
4251
return this;
@@ -49,18 +58,25 @@ public ParseRESTFileCommand build() {
4958

5059
private final byte[] data;
5160
private final String contentType;
61+
private final File file;
5262

5363
public ParseRESTFileCommand(Builder builder) {
5464
super(builder);
5565
this.data = builder.data;
5666
this.contentType = builder.contentType;
67+
this.file = builder.file;
5768
}
5869

5970
@Override
6071
protected ParseHttpBody newBody(final ProgressCallback progressCallback) {
72+
// TODO(mengyan): Delete ParseByteArrayHttpBody when we change input byte array to staged file
73+
// in ParseFileController
6174
if (progressCallback == null) {
62-
return new ParseByteArrayHttpBody(data, contentType);
75+
return data != null ?
76+
new ParseByteArrayHttpBody(data, contentType) : new ParseFileHttpBody(file, contentType);
6377
}
64-
return new ParseCountingByteArrayHttpBody(data, contentType, progressCallback);
78+
return data != null ?
79+
new ParseCountingByteArrayHttpBody(data, contentType, progressCallback) :
80+
new ParseCountingFileHttpBody(file, contentType, progressCallback);
6581
}
6682
}

Parse/src/test/java/com/parse/ParseFileControllerTest.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public void testSaveAsyncNotDirty() throws Exception {
9797
ParseFile.State state = new ParseFile.State.Builder()
9898
.url("http://example.com")
9999
.build();
100-
Task<ParseFile.State> task = controller.saveAsync(state, null, null, null, null);
100+
Task<ParseFile.State> task = controller.saveAsync(state, (byte[])null, null, null, null);
101101
task.waitForCompletion();
102102

103103
verify(restClient, times(0)).execute(any(ParseHttpRequest.class));
@@ -113,15 +113,15 @@ public void testSaveAsyncAlreadyCancelled() throws Exception {
113113

114114
ParseFile.State state = new ParseFile.State.Builder().build();
115115
Task<Void> cancellationToken = Task.cancelled();
116-
Task<ParseFile.State> task = controller.saveAsync(state, null, null, null, cancellationToken);
116+
Task<ParseFile.State> task = controller.saveAsync(state, (byte[])null, null, null, cancellationToken);
117117
task.waitForCompletion();
118118

119119
verify(restClient, times(0)).execute(any(ParseHttpRequest.class));
120120
assertTrue(task.isCancelled());
121121
}
122122

123123
@Test
124-
public void testSaveAsyncSuccess() throws Exception {
124+
public void testSaveAsyncSuccessWithByteArray() throws Exception {
125125
JSONObject json = new JSONObject();
126126
json.put("name", "new_file_name");
127127
json.put("url", "http://example.com");
@@ -154,6 +154,41 @@ public void testSaveAsyncSuccess() throws Exception {
154154
assertEquals("hello", ParseFileUtils.readFileToString(file, "UTF-8"));
155155
}
156156

157+
@Test
158+
public void testSaveAsyncSuccessWithFile() throws Exception {
159+
JSONObject json = new JSONObject();
160+
json.put("name", "new_file_name");
161+
json.put("url", "http://example.com");
162+
String content = json.toString();
163+
164+
ParseHttpResponse response = mock(ParseHttpResponse.class);
165+
when(response.getStatusCode()).thenReturn(200);
166+
when(response.getContent()).thenReturn(new ByteArrayInputStream(content.getBytes()));
167+
when(response.getTotalSize()).thenReturn((long) content.length());
168+
169+
ParseHttpClient restClient = mock(ParseHttpClient.class);
170+
when(restClient.execute(any(ParseHttpRequest.class))).thenReturn(response);
171+
172+
File root = temporaryFolder.getRoot();
173+
ParseFileController controller = new ParseFileController(restClient, root);
174+
175+
File file = new File(root, "test");
176+
ParseFileUtils.writeStringToFile(file, "content", "UTF-8");
177+
ParseFile.State state = new ParseFile.State.Builder()
178+
.name("file_name")
179+
.mimeType("mime_type")
180+
.build();
181+
Task<ParseFile.State> task = controller.saveAsync(state, file, null, null, null);
182+
ParseFile.State result = ParseTaskUtils.wait(task);
183+
184+
verify(restClient, times(1)).execute(any(ParseHttpRequest.class));
185+
assertEquals("new_file_name", result.name());
186+
assertEquals("http://example.com", result.url());
187+
File cachedFile = new File(root, "new_file_name");
188+
assertTrue(cachedFile.exists());
189+
assertEquals("content", ParseFileUtils.readFileToString(cachedFile, "UTF-8"));
190+
}
191+
157192
@Test
158193
public void testSaveAsyncFailure() throws Exception {
159194
// TODO(grantland): Remove once we no longer rely on retry logic.

0 commit comments

Comments
 (0)