WKWebview not rendering .doc file but renders pdf/png/jpeg?

Hello,

This renders a screen with strange characters.

When trying to load a different file type (eg. PDF, PNG, JPEG), it works perfectly.

Also tried loading the .doc data into a UIWebview and it also works fine. I am getting the data from a server using JSON encoded to Base64.

let webview = WKWebView()
webview.load(data, mimeType: "application/msword", characterEncodingName: "UTF-8", baseURL: NSURL() as URL)



Has anyone encountered this issue as well?
File should not save locally.
it is condition.

Accepted Reply

I’m not entirely sure what’s going on here, and you should definitely file a bug about this, especially as

UIWebView
handles it correctly. Please post your bug number, just for the record.

Personally I’d work around this by writing the data to disk and then loading it using

loadFileURL(_:allowingReadAccessTo:)
. However, if your not allowed to do that then you’ll have to explore other options. I managed to get this working using a
data
URL. For example:
let docURL = Bundle.main.url(forResource: "Test", withExtension: "doc")!
let docContents = try! Data(contentsOf: docURL)
let urlStr = "data:application/msword;base64," + docContents.base64EncodedString()
let url = URL(string: urlStr)!
let request = URLRequest(url: url)
self.webView.load(request)

IMPORTANT I can’t guarantee that

WKWebView
doesn’t write this data to disk internally. Which makes a bit of a mockery of the whole “file should not save locally” requirement.

Note I’ve gone against best practice here and built the URL using string primitives rather than

URLComponents
. That’s required because if you use
URLComponents
the semicolon in the
path
property gets encoded as
%3B
. I believe that
URLComponents
is behaving correctly here, but this encoding isn’t supported by
WKWebView
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

I’m not entirely sure what’s going on here, and you should definitely file a bug about this, especially as

UIWebView
handles it correctly. Please post your bug number, just for the record.

Personally I’d work around this by writing the data to disk and then loading it using

loadFileURL(_:allowingReadAccessTo:)
. However, if your not allowed to do that then you’ll have to explore other options. I managed to get this working using a
data
URL. For example:
let docURL = Bundle.main.url(forResource: "Test", withExtension: "doc")!
let docContents = try! Data(contentsOf: docURL)
let urlStr = "data:application/msword;base64," + docContents.base64EncodedString()
let url = URL(string: urlStr)!
let request = URLRequest(url: url)
self.webView.load(request)

IMPORTANT I can’t guarantee that

WKWebView
doesn’t write this data to disk internally. Which makes a bit of a mockery of the whole “file should not save locally” requirement.

Note I’ve gone against best practice here and built the URL using string primitives rather than

URLComponents
. That’s required because if you use
URLComponents
the semicolon in the
path
property gets encoded as
%3B
. I believe that
URLComponents
is behaving correctly here, but this encoding isn’t supported by
WKWebView
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks it works!

Thanks it works!

Cool. But please don’t forget to file that bug.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi,


I am also having the similar issue with WKWebView for docx, doc, rtf files.
I am unable to load these files in WKWebView using any method.
I tried

let fileURL = URL(fileURLWithPath: fileName)

let fileData = FileManager.default.contents(atPath: fileName)!

let pathExtension = fileURL.pathExtension

let mimeType = "application/msword"


Case 1)
wkWebView?.loadFileURL(fileURL, allowingReadAccessTo: fileURL)


Case 2)

webView?.mainFrame.load(fileData, mimeType: mimeType, textEncodingName: "UTF-8", baseURL: URL(fileURLWithPath: fileName))

Case 3)

let fileURLStr = "data:\(mimeType);base64," + fileData.base64EncodedString()

let fileURL_ = URL(string : fileURLStr)!

let request = URLRequest(url: fileURL_)

wkWebView?.load(request)

All the cases works for pdf, txt, csv, jpeg, png files

But for docx, rtf, doc filese, none of the cases work except 2 where it loads data but with encoded characters.
I have a sample app for testing these cases.
Is it possible to successfully load data of these filetypes in WKWebView?

One possible workaround is to write the data into a file and then load the file URL but sometimes this is not a viable solution (e.g. client requirement that no data should be written unencrypted in the file system).


Workaround without writing files on disk

1. Use a custom scheme handler

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
id schemeHandler = ...
[configuration setURLSchemeHandler:schemeHandler forURLScheme:@"someCustomScheme"];
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];


2. Load the data with that custom scheme:

[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL urlWithString:@"someCustomScheme://name.rtf]]];


3. In the scheme handler, provide the data in the protocol method:

- (void)webView:(WKWebView *)webView startURLSchemeTask:(id)urlSchemeTask {
    NSData *data = ...
    NSURLResponse *workaroundResponse =
        [[NSURLResponse alloc] initWithURL:[NSURL urlWithString:@"someCustomScheme://name.rtf] MIMEType:@"application/rtf" expectedContentLength:data.length textEncodingName:@"utf-8"];
    // These three methods must be called and exactly in this order, if not an exception will be thrown
    [urlSchemeTask didReceiveResponse:workaroundResponse];
    [urlSchemeTask didReceiveData:data];
    [urlSchemeTask didFinish];
}


You can check a longer explanation and a working code sample here:

https://github.com/elorz007/WKWebViewRTF

Hello mikel255

Thank you for your code, I tested in iOS and works well. I have a question about mac version, I tried your code in mac, but is not working, do you have any idea about it.

Thanks
Eskimo's answer (with a data-URL approach) worked for me also, although I had a ".docx" instead of a ".doc", so I had to tweak the data type:
Code Block swift
let urlStr = "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64," + docContents.base64EncodedString()