Skip to content
This repository has been archived by the owner on Mar 16, 2019. It is now read-only.

App Crash when downloading PDF from PHP route URL #498

Open
RiusmaX opened this issue Aug 21, 2017 · 3 comments
Open

App Crash when downloading PDF from PHP route URL #498

RiusmaX opened this issue Aug 21, 2017 · 3 comments

Comments

@RiusmaX
Copy link

RiusmaX commented Aug 21, 2017

Hi,

I try to download a dynamically generated PDF from a PHP API, so I do not have a ".pdf" in my url.

Here is the code (URL working via Postman) :

    RNFetchBlob
    .config({
      fileCache: true,
      appendExt: 'pdf'
    })
    .fetch('GET', API + '/xxx/' + xxx.id + '/xxx', {
      headers: {
        'Authorization': 'Bearer ' + this.props.token,
        'Content-Type': 'application/pdf',
        'Accept': 'application/pdf'
      }
    }).then((res) => {
      // do something with the pdf
    }).catch((err) => {
      console.tron.log(err) // not working
    })

The application simply crash with just this information in the XCode console :

[__NSDictionaryM length]: unrecognized selector sent to instance 0x608000449a80
Uncaught exception: -[__NSDictionaryM length]: unrecognized selector sent to instance 0x608000449a80
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryM length]: unrecognized selector sent to instance 0x608000449a80'

Has anyone ever had this problem?
I am in favor of any idea that can help me to solve this problem.

iOS testing version : 10.3
RN version : 0.39.2
RN-fetch-blob version : 0.10.8

Thanks in advance !

@alexandrecanuto
Copy link

alexandrecanuto commented Sep 12, 2017

Same issue here, but trying to upload an image.

Sep 12 12:04:36 MacBook-Air EventApp[66421]: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryM length]: unrecognized selector sent to instance 0x60000045b480'

@cosydney
Copy link

cosydney commented Sep 22, 2017

I have the same issue here while requesting an image. Did you guys found a workaround ?

2017-09-22 10:18:06.211 InMind[10771:1313351] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryM length]: unrecognized selector sent to instance 0x6000002499f0'
*** First throw call stack:
(
	0   CoreFoundation                      0x0000000105994b0b __exceptionPreprocess + 171
	1   libobjc.A.dylib                     0x0000000104821141 objc_exception_throw + 48
	2   CoreFoundation                      0x0000000105a04134 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
	3   CoreFoundation                      0x000000010591b840 ___forwarding___ + 1024
	4   CoreFoundation                      0x000000010591b3b8 _CF_forwarding_prep_0 + 120
	5   CFNetwork                           0x000000010520c883 _ZN15HTTPHeaderValue7isValidEPK10__CFString + 19
	6   CFNetwork                           0x000000010520c7dd _ZN11HTTPMessage25setHeaderFieldStringValueEPK10__CFStringS2_ + 41
	7   CFNetwork                           0x0000000105214a94 _ZN11HTTPMessage23setMultipleHeaderFieldsEPK14__CFDictionary + 124
	8   CFNetwork                           0x000000010528ae8f CFURLRequestSetMultipleHTTPHeaderFields + 126
	9   InMind                              0x0000000103f88723 __85+[RNFetchBlobReqBuilder buildOctetRequest:taskId:method:url:headers:body:onComplete:]_block_invoke + 2455
	10  libdispatch.dylib                   0x00000001097514a6 _dispatch_call_block_and_release + 12
	11  libdispatch.dylib                   0x000000010977a05c _dispatch_client_callout + 8
	12  libdispatch.dylib                   0x0000000109759dcd _dispatch_queue_override_invoke + 1321
	13  libdispatch.dylib                   0x000000010975bec4 _dispatch_root_queue_drain + 634
	14  libdispatch.dylib                   0x000000010975bbef _dispatch_worker_thread3 + 123
	15  libsystem_pthread.dylib             0x0000000109b115a2 _pthread_wqthread + 1299
	16  libsystem_pthread.dylib             0x0000000109b1107d start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
@RiusmaX
Copy link
Author

RiusmaX commented Sep 25, 2017

I've found a solution, not perfect but it's working for me with base64 encoded PDF on Android & iOS:

First, replace built-in fetch

const fetchPdf = new Fetch({
  auto: true,
  binaryContentTypes: ['image/', 'video/', 'audio/', 'application/', '/pdf']
}).build()

class Pdf extends React.Component { ... }

And it's my method for downloading PDF (for Android you need to get write storage permission with PermissionsAndroid from RN) :

 downloadDelivery = () => {
    this.setState({fetching: true})
    const file = '/file.pdf'
    const url = API + '/xxx'
    if (Platform.OS === 'android') {
      if (this.state.havePermission) {
        RNFetchBlob
        .config({
          addAndroidDownloads: {
            useDownloadManager: true,
            notification: false,
            path: RNFetchBlob.fs.dirs.DownloadDir + file,
            mime: 'application/pdf;base64',
            title: I18n.t('appTitle'),
            description: I18n.t('shippingForm')
          }
        })
        .fetch('GET', url, {
          Authorization: 'Bearer ' + this.props.token,
          'Content-Type': 'application/pdf;base64'
        })
        .then((resp) => {
          this.setState({fetching: false})
          RNFetchBlob.android.actionViewIntent(resp.data, 'application/pdf')
        })
        .catch((errorCode, errorMessage) => {
          this.setState({fetching: false})
          console.tron.log({error: errorCode, message: errorMessage})
          Alert.alert(I18n.t('dataError'))
        })
      } else {
        Alert.alert(I18n.t('noWritePermission'))
        this.setState({fetching: false})
      }
    } else {
      fetchPdf(url, {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer ' + this.props.token,
          'Content-Type': 'application/pdf;base64'
        }
      }).then((resp) => {
        const base64Str = resp.resp.data
        const dir = RNFetchBlob.fs.dirs.DocumentDir + file
        RNFetchBlob.fs.readFile(base64Str, 'base64')
        .then((data) => {
          RNFetchBlob.fs.createFile(dir, data, 'base64').then(() => {
            this.setState({fetching: false})
            RNFetchBlob.ios.openDocument(dir)
          }).catch((err) => {
            this.setState({fetching: false})
            console.tron.log(err)
          })
        })
      }).catch((errorCode, errorMessage) => {
        this.setState({fetching: false})
        console.tron.log({error: errorCode, message: errorMessage})
        Alert.alert(I18n.t('dataError'))
      })
    }
}

If you find a better way, please share it :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.