mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-03 22:48:25 +08:00
Implement Blob support for XMLHttpRequest
Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
This commit is contained in:
committed by
Facebook Github Bot
parent
3fc33bb54f
commit
be56a3efee
@@ -26,6 +26,7 @@ rn_robolectric_test(
|
||||
react_native_target("java/com/facebook/react/common/network:network"),
|
||||
react_native_target("java/com/facebook/react/devsupport:interfaces"),
|
||||
react_native_target("java/com/facebook/react/jstasks:jstasks"),
|
||||
react_native_target("java/com/facebook/react/modules/blob:blob"),
|
||||
react_native_target("java/com/facebook/react/modules/camera:camera"),
|
||||
react_native_target("java/com/facebook/react/modules/clipboard:clipboard"),
|
||||
react_native_target("java/com/facebook/react/modules/common:common"),
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.blob;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
@PrepareForTest({Arguments.class})
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
@Config(manifest = Config.NONE)
|
||||
public class BlobModuleTest {
|
||||
|
||||
private byte[] mBytes;
|
||||
private String mBlobId;
|
||||
private BlobModule mBlobModule;
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
@Before
|
||||
public void prepareModules() throws Exception {
|
||||
PowerMockito.mockStatic(Arguments.class);
|
||||
Mockito.when(Arguments.createMap()).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new JavaOnlyMap();
|
||||
}
|
||||
});
|
||||
|
||||
mBytes = new byte[120];
|
||||
new Random().nextBytes(mBytes);
|
||||
|
||||
mBlobModule = new BlobModule(ReactTestHelper.createCatalystContextForTest());
|
||||
mBlobId = mBlobModule.store(mBytes);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
mBlobModule.remove(mBlobId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolve() {
|
||||
assertArrayEquals(mBytes, mBlobModule.resolve(mBlobId, 0, mBytes.length));
|
||||
byte[] expectedRange = Arrays.copyOfRange(mBytes, 30, mBytes.length);
|
||||
assertArrayEquals(expectedRange, mBlobModule.resolve(mBlobId, 30, mBytes.length - 30));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveUri() {
|
||||
Uri uri = new Uri.Builder()
|
||||
.appendPath(mBlobId)
|
||||
.appendQueryParameter("offset", "0")
|
||||
.appendQueryParameter("size", String.valueOf(mBytes.length))
|
||||
.build();
|
||||
|
||||
assertArrayEquals(mBytes, mBlobModule.resolve(uri));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveMap() {
|
||||
JavaOnlyMap blob = new JavaOnlyMap();
|
||||
blob.putString("blobId", mBlobId);
|
||||
blob.putInt("offset", 0);
|
||||
blob.putInt("size", mBytes.length);
|
||||
|
||||
assertArrayEquals(mBytes, mBlobModule.resolve(blob));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
assertNotNull(mBlobModule.resolve(mBlobId, 0, mBytes.length));
|
||||
|
||||
mBlobModule.remove(mBlobId);
|
||||
|
||||
assertNull(mBlobModule.resolve(mBlobId, 0, mBytes.length));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFromParts() {
|
||||
String id = UUID.randomUUID().toString();
|
||||
|
||||
JavaOnlyMap blobData = new JavaOnlyMap();
|
||||
blobData.putString("blobId", mBlobId);
|
||||
blobData.putInt("offset", 0);
|
||||
blobData.putInt("size", mBytes.length);
|
||||
JavaOnlyMap blob = new JavaOnlyMap();
|
||||
blob.putMap("data", blobData);
|
||||
blob.putString("type", "blob");
|
||||
|
||||
String stringData = "i \u2665 dogs";
|
||||
byte[] stringBytes = stringData.getBytes(Charset.forName("UTF-8"));
|
||||
JavaOnlyMap string = new JavaOnlyMap();
|
||||
string.putString("data", stringData);
|
||||
string.putString("type", "string");
|
||||
|
||||
JavaOnlyArray parts = new JavaOnlyArray();
|
||||
parts.pushMap(blob);
|
||||
parts.pushMap(string);
|
||||
|
||||
mBlobModule.createFromParts(parts, id);
|
||||
|
||||
int resultSize = mBytes.length + stringBytes.length;
|
||||
|
||||
byte[] result = mBlobModule.resolve(id, 0, resultSize);
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(resultSize);
|
||||
buffer.put(mBytes);
|
||||
buffer.put(stringBytes);
|
||||
|
||||
assertArrayEquals(result, buffer.array());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRelease() {
|
||||
assertNotNull(mBlobModule.resolve(mBlobId, 0, mBytes.length));
|
||||
|
||||
mBlobModule.release(mBlobId);
|
||||
|
||||
assertNull(mBlobModule.resolve(mBlobId, 0, mBytes.length));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user