android专家...我正在搜索灾难。我有一个嵌入在表单应用中的Webview,该应用程序还具有为其实现的自定义渲染器(用于WebView(。
我正在包装一个基本的Web应用程序(SAP Fiori(,在该应用程序中,它有一个薪水声明部分,用户可以在其中查看其工资单。在该页面上,有一个按钮可以下载薪水。
在我的应用程序中的iOS中,所有这些都可以作为标准化,即PDF打开并在浏览器中查看。在Android和iOS上,任何浏览器(例如Chrome或Safari(也可以正常工作。
在我的Android应用中,单击"打开为PDF"按钮不会产生结果,前端什么也没有发生,但是在应用程序本身中,实现的下载列表方法是触发的...
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
Control.Settings.AllowUniversalAccessFromFileURLs = true;
Control.SetWebViewClient(new MySAPWebViewClient(Context));
Control.SetDownloadListener(new MySAPDownloadListener());
}
public class MySAPDownloadListener : Java.Lang.Object, IDownloadListener
{
public new void Dispose() { }
public void OnDownloadStart(string url, string userAgent, string contentDisposition, string mimetype, long contentLength)
{
System.Diagnostics.Debug.WriteLine("Url = " + url);
System.Diagnostics.Debug.WriteLine("Content Disposition = " + contentDisposition);
System.Diagnostics.Debug.WriteLine("Mime Type = " + mimetype);
}
}
这些是主要的下loadeventargs值...
url = "https://organisation.com/sap/opu/odata/sap/HCM_MY_PAYSTUBS_SRV/PDFPaystubs(SEQUENCENUMBER=189,PersonnelAssignment='00044411')/$value"
contentDisposition = "inline; filename=Paystub_01.31.2018.pdf"
mimetype = "application/pdf"
...现在,在该URL后面,有一块JavaScript生成动态PDF,因此它没有存储在服务器上的任何地方,这似乎是我遇到问题的地方。
我在线阅读的所有内容都说要使用httpclient下载pdf的内容以归档,然后将其打开。但是,如果我将该URL传递给HTTPCLIENT,我没有得到PDF数据,我会得到HTML文本。
我在Stackoverflow上尝试了GoogleDocs和许多其他链接,但是无论我做什么,URL都返回HTML文本,而不是PDF文档的内容。
我对SAP也给我的东西几乎没有控制权,因此更改服务器端是一个不太可能的选择。
任何帮助都将不胜感激。
您可以通过两个解决方案来执行此操作:
解决方案1:在系统默认浏览器中打开URL。
private async Task MWebview_Download(object sender, DownloadEventArgs e)
{
await Launcher.OpenAsync(e.Url);
}
解决方案2 使用httpclient下载。
private async void MWebview_Download(object sender, DownloadEventArgs e)
{
string fileName = GetFileName(e);
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(MainActivity.Instance, "Downloading File...", ToastLength.Long).Show();
});
await DownloadPdfFile(e, fileName);
}
private async Task DownloadPdfFile(DownloadEventArgs e, string fileName)
{
try
{
//Bypass the certificate
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
// Getting Cookie
String cookies = CookieManager.Instance.GetCookie(e.Url);
var client = new HttpClient(clientHandler);
var httpRequestMessage = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(e.Url),
Headers = {
{ HttpRequestHeader.TransferEncoding.ToString(), "binary" },
{ HttpRequestHeader.ContentLength.ToString(), e.ContentLength+"" },
{ HttpRequestHeader.ContentType.ToString(), "application/pdf" },
{HttpRequestHeader.Cookie.ToString(),cookies },
},
};
// Api Call
var response = await client.SendAsync(httpRequestMessage);
// Read content as Byte[]
var bytes = response.Content.ReadAsByteArrayAsync().Result;
// Save to Local DB
var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
var filePath = Path.Combine(documentsPath, fileName);
// convert byte to stream
MemoryStream stream = new MemoryStream(bytes);
// Write file
SaveAndView(fileName, "application/pdf", stream);
}
catch (Exception ee)
{
Toast.MakeText(MainActivity.Instance, "Failed !!", ToastLength.Long).Show();
}
}
public void SaveAndView(string fileName, String contentType, MemoryStream stream)
{
string exception = string.Empty;
string root = null;
if (ContextCompat.CheckSelfPermission(MainActivity.Instance, Manifest.Permission.WriteExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions((Activity)MainActivity.Instance, new String[] { Manifest.Permission.WriteExternalStorage }, 1);
}
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
else
root = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
Java.IO.File myDir = new Java.IO.File(root + "/PDFFiles");
myDir.Mkdir();
Java.IO.File file = new Java.IO.File(myDir, fileName);
if (file.Exists()) file.Delete();
try
{
FileOutputStream outs = new FileOutputStream(file);
outs.Write(stream.ToArray());
outs.Flush();
outs.Close();
}
catch (Exception e)
{
exception = e.ToString();
}
if (file.Exists() && contentType != "application/html")
{
string extension = MimeTypeMap.GetFileExtensionFromUrl(Android.Net.Uri.FromFile(file).ToString());
string mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension);
Intent intent = new Intent(Intent.ActionView);
intent.SetFlags(ActivityFlags.ClearTop | ActivityFlags.NewTask);
Android.Net.Uri path = FileProvider.GetUriForFile(MainActivity.Instance, Android.App.Application.Context.PackageName + ".provider", file);
intent.SetDataAndType(path, mimeType);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
MainActivity.Instance.StartActivity(Intent.CreateChooser(intent, "Choose App"));
}
}
注意:确保处理FileProvider:
**Changes in Manifest file:**
- Add android:requestLegacyExternalStorage="true" in application tag
- Add between application tag
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false" android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
添加XMARIN.ANDROID项目中的XML文件夹中的file_paths.xml。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="Pictures" />
<external-files-path name="my_movies" path="Movies" />
<external-path name="external_files" path="."/>
</paths>
不幸的是,由于某些原因,Android WebView无法显示PDF文件。因此,如果使用WebView对您至关重要,那么只有一个选项 - 使用Google Docs Viewer。但这仅适用于通过公共URL提供的PDF。它看起来像这样:
WebView view=(WebView)findViewById(R.id.webView);
view.setWebViewClient(new WebViewClient());
String url=getIntent().toString("value1");
String URL="https://docs.google.com/viewer?url="+url;
view.loadUrl(Url);
如果使用WebView不是那么重要,则可以使用:
- 一些第三方库显示PDF
- 致电通过另一个应用显示PDF的意图
- 如果您使用API级别21及以上 - 您可以用Android PDFrenderer弄脏手
希望它能帮助