Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-23309] Android: pdf and xls files with response headers (Content-Type →application/octet-stream) not opening with Ti sdk 5.0.0,5.1.1, 5.2.0

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2016-07-11T06:48:45.000+0000
Affected Version/sRelease 5.4.0, Release 5.3.0
Fix Version/sRelease 6.0.0
ComponentsAndroid
LabelsAndroid
ReporterParween Singh
AssigneeAshraf Abu
Created2016-04-26T10:20:46.000+0000
Updated2016-08-16T22:05:35.000+0000

Description

Steps to Reproduce

Download the Sample Pdf Viewer Code from 'https://gist.github.com/lbrenman/fa5195aba08d1b5e8fa0' Replace the url in line no 66, index.js file with 'http://dev-cms-molpower.trafficmanager.net/ServiceProfileFileHandler.ashx?svc=CMI&file=FirstSchedule.pdf' for pdf. On clicking the URL button . We get an alert 'This document cannot be opened'. The same works with Ti SDK 4.0.0.

Actual Result

Pdf / Xls not getting opened

Expected Result

The pdf should be opened successfully

Attachments

FileDateSize
.log2016-04-26T10:20:50.000+00000
diagnostic5508536153902136859.log2016-04-26T10:22:11.000+0000117068

Comments

  1. Nazmus Salahin 2016-04-28

    Hello, I am able to reproduce this issue. It seems that when build with SDK 5.2.2.GA downloaded pdf file becomes corrupted. *Setps:* 1. Create a default alloy project. 2. Replace corresponding file code with following. *index.js :*
       function resourcePDF(e) {
       	openResourcePDF();
       }
       
       function urlPDF(e) {
       	openURLPDF();
       }
       
       function viewPDF(appfilepath) {
       	if (OS_ANDROID) {
       		try {
       			Ti.Android.currentActivity.startActivity(Ti.Android.createIntent({
       				action : Ti.Android.ACTION_VIEW,
       				type : 'application/pdf',
       				data : appfilepath
       			}));
       		} catch(e) {
       			Ti.API.info('error trying to launch activity, e = ' + e);
       			alert('No PDF apps installed!');
       		}
       	} else {
       		docViewer = Ti.UI.iOS.createDocumentViewer({
       			url : appfilepath
       		});
       		docViewer.show();
       	}
       }
       
       function openResourcePDF() {
       	var appFile;
       
       	if (OS_ANDROID) {
       		//copy from app directory to SDCard (once)
       		var originalFile = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, 'pdf/sample.pdf');
       		appFile = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, 'sample.pdf');
       		if (appFile.exists() === false) {
       			appFile.write(originalFile.read());
       		}
       	} else {
       		appFile = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, 'pdf/sample.pdf');
       	}
       	var appfilepath = appFile.nativePath;
       
       	viewPDF(appfilepath);
       }
       
       function openURLPDF() {
       	var appFile;
       
       	if (OS_ANDROID) {
       		appFile = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, 'map.pdf');
       	} else {
       		appFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'map.pdf');
       	}
       	var appfilepath = appFile.nativePath;
       
       	//Check if file has been downloaded yet
       	if (appFile.exists() === false) {
       		var xhr = Ti.Network.createHTTPClient();
       		xhr.onload = function() {
       			appFile.write(this.responseData);
       			viewPDF(appfilepath);
       		};
       		xhr.onerror = function() {
       			alert("Cannot retrieve PDF form web site");
       		};
       		xhr.timeout = 10000;
       		xhr.open("GET", "http://dev-cms-molpower.trafficmanager.net/ServiceProfileFileHandler.ashx?svc=CMI&file=FirstSchedule.pdf");
       		xhr.send();
       
       	} else {
       		viewPDF(appfilepath);
       	}
       }
       
       $.index.open();
       
    *index.tss :*
       ".container": {
       	backgroundColor:"white"
       }
       
       "Label": {
       	width: Ti.UI.SIZE,
       	height: Ti.UI.SIZE,
       	color: "#000"
       }
       
       "#label": {
       	font: {
       		fontSize: 12
       	}
       }
       
    *index.xml :*
       <Alloy>
       	<Window class="container">
       		<View top="100" layout="vertical">
       			<Button top="20" title="App Resource" onClick="resourcePDF"/>
       			<Button top="20" title="URL" onClick="urlPDF"/>
       		</View>>
       	</Window>
       </Alloy>
       
    4. Build and run the app with SDK 4.0.0.GA. 5. Click URL button. >> PDF will be downloaded >> PDF will be shown.[Screenshot](https://i.imgsafe.org/6692c1b.png) 6. Now build and run the app with SDK 5.2.2.GA. 7. Click URL button >> >> PDF will be shown. Note: PDF is already download with previous steps and does exists in storage. 9. Delete the PDF from storage manually. 10. Run the app again and Click URL button. PDF will be downloaded (or may be not but written in storage anyway). >> "Document cannot be opened" alert shown.[Screenshot](https://i.imgsafe.org/b4eaa76.png) Note: No error log is produced 12. Build and run the app with SDK 4.0.0.GA again. 13. Click URL button. >> "Document cannot be opened" alert shown. 14. Delete the PDF from storage manually. 15. Click URL button. >> PDF will be downloaded >> PDF will be shown. *Environment*: *Device info:* HTC One (Android 4.4.3) *Node.js Version:* 0.12.7 *npm Version:* 2.11.3 *Titanium SDKs:* 5.2.2.GA and 5.2.1.GA *Java Development Kit Version:* 1.8.0_73 *Titanium CLI Version:* 5.0.5 *Appcelerator CLI Version:* 5.2.2 *Appcelerator Studio:* 4.5.0
  2. Chee Kiat Ng 2016-05-04

    [~nsalahin] Can you also reproduce using sdk < 5.0.0 to see if it's a valid regression.
  3. Hieu Pham 2016-05-25

    [~nsalahin] Can you include the PDF file that you tested for consistency purposes? Thanks,
  4. Ashraf Abu 2016-06-06

       xhr.onload = function() {
       			Ti.UI.createAlertDialog({
       			      title:'Success',
       			      message:'status code ' + this.status
       		    }).show();
       			appFile.write(this.responseData);
       		};
       
    When you add this into the test code, you will get a Status 302. "Object moved" with the URL 'http://dev-cms-molpower.trafficmanager.net/ServiceProfileFileHandler.ashx?svc=CMI&file=FirstSchedule.pdf'. When you use the relocated url "https://molprdeastus.blob.core.windows.net/molpowercmsprodcontent/Content/ServicesNSchedules/Network/CMI/FirstSchedule.pdf" , you can download it.
  5. Ashraf Abu 2016-06-06

    This is due to the redirect from http to https.
  6. Ashraf Abu 2016-06-06

    There is a change in behaviour as we are now using HttpURLConnection in the SDK from SDK 5 onwards. This document explains the issue. Android docs https://developer.android.com/reference/java/net/HttpURLConnection.html :- {quote} Response Handling HttpURLConnection will follow up to five HTTP redirects. It will follow redirects from one origin server to another. This implementation doesn't follow redirects from HTTPS to HTTP or vice versa. {quote} The problem in this case is that the original url is "HTTP" and the relocated/redirected url is "HTTPS". That is why it doesn't follow through. This is how Android is behaving.
  7. Ashraf Abu 2016-06-06

    Thus, to get this working, you should get the new relocated url and open another connection. This will download the file. Example:-
       function openURLPDF() {
       	var appFile;
        
       	if (OS_ANDROID) {
       		appFile = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, 'map.pdf');
       	} else {
       		appFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'map.pdf');
       	}
       	var appfilepath = appFile.nativePath;
        
       	//Check if file has been downloaded yet
       	if (appFile.exists() === false) {
       		var xhr = Ti.Network.createHTTPClient();
       		xhr.onload = function() {
       		    Ti.API.info('status code ' + this.status);
       		    Ti.API.info(this.responseData);
       		    Ti.API.info(this.getResponseHeader("Location"));
       		    var redirected = this.getResponseHeader("Location");
       		    if (this.status == 302) {
       			    var xhr = Ti.Network.createHTTPClient();
       				xhr.onload = function() {
       					appFile.write(this.responseData);
       					viewPDF(appfilepath);
       				}
       				xhr.timeout = 10000;
       				xhr.open("GET", redirected);
       				xhr.send()
       		    }
       		    
       		};
       		xhr.onerror = function() {
       			alert("Cannot retrieve PDF form web site");
       		};
       		xhr.timeout = 10000;
       		xhr.open("GET", "http://dev-cms-molpower.trafficmanager.net/ServiceProfileFileHandler.ashx?svc=CMI&file=FirstSchedule.pdf");
       		xhr.send();
       	} else {
       		viewPDF(appfilepath);
       	}
       	
       	
       }
       
  8. Ashraf Abu 2016-06-06

    -Resolving issue as solution is provided above.-
  9. Ashraf Abu 2016-06-07

    Code above is a workaround for now while a fix is in progress.
  10. Ashraf Abu 2016-06-07

    PR for review: https://github.com/appcelerator/titanium_mobile/pull/8043
  11. Parween Singh 2016-06-22

    Tested the workaround provided by Ashraf Abu with Ti sdk 5.2.0 . It works as expected. Thanks.
  12. Ashraf Abu 2016-06-23

    Welcome. There is a fix in the coming up 6.0.0 that would not require this workaround.
  13. Ashraf Abu 2016-07-11

    PR Merged.
  14. Lokesh Choudhary 2016-08-16

    Verified the fix. Closing. Environment: Appc Studio : 4.7.0.201607250649 Ti SDK : 6.0.0.v20160816021339 Ti CLI : 5.0.9 Alloy : 1.9.1 MAC El Capitan : 10.11.6 Appc NPM : 4.2.7 Appc CLI : 6.0.0-24 Node: 4.4.4 Nexus 6 - Android 6.0.1

JSON Source