无法使用React Native RNFetchBlob从android设备删除图像

时间:2019-03-05 11:31:06

标签: react-native react-native-android react-native-fetch-blob

我想开发一个可以拍照并上传到AWS s3的应用程序。现在,我要在上传后从图库中删除拍摄的图像。

通过使用RNFetchBlob库,我能够实现这一目标。拍摄后,我试图删除一次图像。运行良好。但是,我想在上传到云后将其删除一次。因此,我创建了一个方法来执行此操作,并且有一个名为isUploaded的变量,该变量被设置为false,一旦上传完成,我就将该变量状态设置为true,而在render方法中,我将其称为delete images方法。但这不是删除图像。我没弄错地方。

您能帮我解决这个问题吗?

export default class Upload extends Component {

constructor(props) {
    super(props);
      storeFilePath :[],
      saveImages :[],
      isUploaded:false
    }
  }

takePic = async function() {

      var date = new Date();
      var time = date.getTime();
      this.setState({capturedTime:time});

       console.log(this.state.connection_Status);

     if(this.state.connection_Status==="Online"){
        this.getServerTime();
        this.setState({capturedTime:this.state.serverTime.currentFileTime+'_'+time});
        console.log(this.state.capturedTime); 
        console.log("availble");
      } 
        const options = {
          quality: 1.0,
          maxWidth: 75,
          maxHeight: 75,
          base64: true
      }

    ImagePicker.launchCamera(options,(responce)=>{

       this.state.testImage.push({ uri: responce.uri });

      const file ={
        uri : responce.uri,
        name : responce.fileName;
        method: 'POST',
        width : 50,
        height : 50,
        path : responce.path,
        type :  responce.type,
        notification: {
            enabled: true
          }
      }
        this.state.saveImages.push(file);
        this.state.storeFilePath.push(responce.path);

    })
  }

  _upload=(saveImages)=>{
      const config ={
          keyPrefix :'***/',
          bucket : '****',
          region :'***',
          accessKey:'**************',
          secretKey :'**/*+*****',
          successActionStatus :201
        }

        this.state.saveImages.map((image) => {
         RNS3.put(image,config)
        .then((responce) => {
            console.log('=============********************================');
            console.log(image);
            this.setState({ isUploaded: true }); 
          });
        });

        Alert.alert('Successfully, saved');
      } 

  deleteImages=(storeFilePath)=>{
    this.state.storeFilePath.map((path) => {
      RNFetchBlob.fs.unlink(path)
        .then(() => {
          console.log('Delete images once after file upload is done');
        });
      });
  }

  render() {
      return (

          if(this.state.isUploaded===true){
              this.deleteImages(this.state.storeFilePath);
          } 

        <View>
          <View style={styles.Camera}>
            <TouchableOpacity onPress={this.takePic.bind(this)}>
              <Text>Take Picture</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.Send}>
            <TouchableOpacity onPress={() => this._upload()}>
              <Text>Send</Text>
            </TouchableOpacity>
          </View>
        </View>
      );
  }
}

1 个答案:

答案 0 :(得分:0)

takePic

您正在通过takePic函数更改状态

this.state.saveImages.push(file);
this.state.storeFilePath.push(responce.path);

这可能导致您的状态更新时突变消失。这可能意味着您上传的图像由于路径丢失而没有被删除。

您应该正确地调用setState,方法是获取状态的先前值,添加新值,然后对其进行更新。

this.setState(prevState => {
  // get the previous state values for the arrays
  let saveImages = prevState.saveImages;
  let storeFilePath = prevState.storeFilePath;

  // add the values to the arrays like before
  saveImage.push(file);
  storeFilePath.push(responce.path);

  // return the new state
  return {
   saveImages, 
   storeFilePath
  }
});

如果您想检查状态是否刚刚设置,则应该执行以下操作:

this.setState({capturedTime:this.state.serverTime.currentFileTime+'_'+time});
console.log(this.state.capturedTime); // <- this is not guaranteed to be correct

应使用 setState随附的回调函数。您应该将代码更新为:

this.setState({capturedTime:this.state.serverTime.currentFileTime+'_'+time}, 
  () => console.log(this.state.capturedTime)
);

这将确保state已被更新,以便您的console.log应该为您显示正确的值。

deleteImages

deleteImages函数中,您正在传递参数storeFilePath,但由于直接从storeFilePath访问state而不使用它。

deleteImages=(storeFilePath)=>{ // <- storeFilePath is not used
    this.state.storeFilePath.map((path) => {
      RNFetchBlob.fs.unlink(path)
        .then(() => {
          console.log('Delete images once after file upload is done');
        });
      });
}

您可以使用它并将函数重写为:

deleteImages=(storeFilePath)=>{ 
    storeFilePath.map((path) => {
      RNFetchBlob.fs.unlink(path)
        .then(() => {
          console.log('Delete images once after file upload is done');
        });
      });
}

或者您可以一起忽略该参数并执行以下操作:

deleteImages=()=>{ 
    this.state.storeFilePath.map((path) => {
      RNFetchBlob.fs.unlink(path)
        .then(() => {
          console.log('Delete images once after file upload is done');
        });
      });
}

渲染

您不应该在deleteImages中调用render函数。您应该使用React组件的生命周期方法。

我们可以使用componentDidUpdate检查图像是否已上传,然后致电  deleteImages

componentDidUpdate(prevProps, prevState) {
  if (this.state.isUploaded) {
    this.deleteImages(); // <- see above about refactoring this function
  }
}

_upload

我不是100%确信这是上传的正确方法。就像在deleteImages中一样,您没有使用要传递的参数。

_upload=(saveImages)=>{
   const config ={ ... }

   this.state.saveImages.map((image) => {
     RNS3.put(image,config)
    .then((responce) => {
        console.log('=============********************================');
        console.log(image);
        this.setState({ isUploaded: true }); 
      });
    });

    Alert.alert('Successfully, saved');
 } 

我认为您可能应该使用Promise.all(似乎更多here)来处理这些问题。此外,您上传的每个图像都会调用this.setState({ isUploaded: true });,触发重新渲染并调用deleteImages函数,因为状态现在为true。这样的事情可能会更好:

_upload () => { // <- again you are not using the parameter that you are passing
  const config = { ... }
  Promise.all(this.state.saveImages.map(image => RNS3.put(image, config))).then(values => {
    this.setState({isUploaded: true});
    alert('Successfully, saved);
    // though why delete images on a state change, why not delete them here now that the upload has completed?
  })
}

以下是setState上的一些很棒的文章。