react-nativeexpo

Convert content:// uri to file:// uri using react native


I'm currently trying to open a file using expo's FileSystem after getting the path from expo's DocumentPicker, but I can't find a way to make the URI from DocumentPicker readable to FileSystem. Everything works fine, I've no problems with permissions or anything else, but every tutorial I could find so far are basically for react native projects with exposed native code or Java.

Here I call DocumentPicker:

import * as DocumentPicker from 'expo-document-picker';

const Hello = ({navigation}) => (
  <HelloView>
    <HelloButton
      style={{
        backgroundColor: WhatsappStyles.colors.lightGreen,
      }}
      activeOpacity={0.5}
      onPress={() => {
        DocumentPicker.getDocumentAsync({
          copyToCacheDirectory: false,
        }).then(({uri}) => {
          navigation.navigate('LoadFile', {path: uri});
        });
      }
    }>
      <HelloButtonText>Go to App</HelloButtonText>
    </HelloButton>
  </HelloView>
);

And here I try (unsuccessfully) read the path:

import * as FileSystem from 'expo-file-system';


const LoadFile = ({navigation, route}) => {
  let [loading, setLoading] = useState(true);

  useEffect(() => {
    FileSystem.readAsStringAsync(route.params.path).then(result => {
    // do something here
    }
    setLoading(false);
  }, []);
...

I'm using react-navigation/stack for stack navigation and styled-components/native to build the components.


Solution

  • So, as far as I could find there's no way to "convert" content:// uri to file:// uri, but you can actually download the file to a cache or to the internal storage using FileSystem's downloadAsync function and use the file:// uri resulting from there.

    e.g.

    DocumentPicker.getDocumentAsync({
        copyToCacheDirectory: false,
    }).then(({contentUri}) => {
        FileSystem.downloadAsync(
             contentUri, 
             FileSystem.documentDirectory + '<file name>')
        .then(({uri}) => {
             FileSystem.readAsStringAsync(uri)
             .then(result => {
                  // do what you want here.
             });
        });
    });