Save remote image to camera roll in React Native?

2020-06-19 04:23发布

I'm getting nothing but errors from the ReactNative CameraRoll's saveImageWithTag function. Saving a local image with something like:

CameraRoll.saveImageWithTag('./path/to/myimage.png');
      .then(res => console.log(res))
      .catch(err => console.log(err));

gives me the error:

Error: The file “myimage.png” couldn’t be opened because there is no such file.(…)

./path/to/myimage.png in this case is the path I'd use to require an image for an Image source. What should the full path be for a local image be? Do I need to store them differently to make them accessible?

2条回答
姐就是有狂的资本
2楼-- · 2020-06-19 05:05

0. Short answer

Use RNFS to locate the local image.

1. For your title 'Save remote image to camera roll in React Native'

The keyword is remote.

Before using CameraRoll, we should link the library first.

enter image description here

Then, I create one Image and one Button:

  render: function() {
    return (
      <View style={styles.container}>
          <Image ref="logoImage"
            style={{ height:50, width: 50 }}
            source={{uri: 'http://facebook.github.io/react/img/logo_og.png'}}
          />
          <TouchableHighlight style={styles.button} onPress={this._handlePressImage} underlayColor='#99d9f4'>
            <Text style={styles.buttonText}>Save Image</Text>
          </TouchableHighlight>
      </View>
    );
  },

When I press the button, the program will save the image to camera roll:

  _handlePressImage: function() {
    console.log('_handlePressImage.');

    var uri = this.refs.logoImage.props.source;
    console.log(uri);
    CameraRoll.saveImageWithTag(uri, function(result) {
      console.log(result);
    }, function(error) {
      console.log(error);
    });
  },

React Native warns me that the API is deprecated, just use promise instead:

var promise = CameraRoll.saveImageWithTag(uri);
promise.then(function(result) {
  console.log('save succeeded ' + result);
}).catch(function(error) {
  console.log('save failed ' + error);
});

Now, we can see the logo image in our camera roll.

2. For your real problem in your content

Despite your title says remote, your code uses the local path.

Give the path './path/to/myimage.png', I assume that the image path is relative to the .js file. That is, your image is not relative to the final running app, so it can not find the image file.

Now change the Image to use local file:

<Image ref="logoImage"
  style={{ height:50, width: 50 }}
  source={require('./logo_og.png')}
/>

and save the image like this:

var promise = CameraRoll.saveImageWithTag('./logo_og.png');

which results in:

enter image description here

Because CameraRoll API is corresponding to the Native Component, which belongs to the final running app, not the javascript.

3. Use RNFS to save local images

First run the command below:

npm install react-native-fs --save

and then link the library.

After Putting the image under Library/Caches:

enter image description here

we can save the local image:

var cacheImagePath = RNFS.CachesDirectoryPath+"/logo_og.png";
console.log(cacheImagePath);
var promise = CameraRoll.saveImageWithTag(cacheImagePath);
promise.then(function(result) {
  console.log('save succeeded ' + result);
}).catch(function(error) {
  console.log('save failed ' + error);
});

enter image description here

Thanks.

查看更多
不美不萌又怎样
3楼-- · 2020-06-19 05:14

Use this saveToCameraRoll method.

import { CameraRoll } from 'react-native';

 CameraRoll.saveToCameraRoll(url)
    .then(alert('Done', 'Photo added to camera roll!')) 
    .catch(err => console.log('err:', err))
}

The user's permission is required in order to access the Camera Roll on devices running iOS 10 or later. Add the NSPhotoLibraryUsageDescription key in your Info.plist with a string that describes how your app will use this data. This key will appear as Privacy - Photo Library Usage Description in Xcode. If you are targeting devices running iOS 11 or later, you will also need to add the NSPhotoLibraryAddUsageDescription key in your Info.plist.

查看更多
登录 后发表回答