I try enable GZip compression for improve connection performance between client and server, but it seems that WebView doesn't decompress GZip-response.
Response Header(from server) contains:
Content-Encoding:gzip
Content-Type:application/gzip
Body contains compressed JSON
On the Desktop browsers all fine,
but if it is android device in Chrome DevTools I see compressed body.
Mobile app doesn't decompress response body.
Created issue https://issues.apache.org/jira/browse/CB-9427
When I have changed content type into 'application/json' problem was solved.
Here sample from Grape framework app:
module App
class Users < API
resource :users do
format :json
content_type :txt, "application/json"
parser :json, nil
desc "Get users"
params do
optional :role, type: String, desc: "User's role"
end
get '/all' do
users = User.all
path = "#{Rails.root.to_s}/tmp/user_response.gz"
FileUtils.rm_rf(path, secure: true)
Zlib::GzipWriter.open(path){|gz| gz.write(users.to_json) }
content_type "application/json"
header['Content-Encoding'] = 'gzip';
env['api.format'] = :json
File.open(path).read
end
end
end
end
Issue https://issues.apache.org/jira/browse/CB-9427 was closed.
Thanks to cordova support team!
Related
I need to download, from a mobile app developed in flutter 1.22.2, a file generated by a php script. The file is available in blob format.
The javascript code in the web page is:
response.blob()
.then(blob => URL.createObjectURL(blob))
.then(url => {
let a = document.createElement('a');
a.href = url;
a.download = 'modulo-' + JobRiskIden + '.pdf';
a.target = '_blank';
document.body.appendChild(a);
a.click()
a.remove();
})
Where "response" variable is the response from a fetch to a php page that generates the file.
I followed the instructions from this stackoverflow question:
Flutter WebView blob pdf download
The download works fine on iOS but an issue is present on Android (test done with compileSdkVersion 29): when I tap on the download link the debugger prints this message:
{message: Not allowed to load local resource: blob:https://apps.badgebox.com/62edb40f-4407-4d3b-8427-587ea133b778, messageLevel: 3}
Can someone help me to solve this issue?
Only after visiting almost all Stack Overflow links for the same answer, I was compelled to write this,
I am trying to display a PDF file in the WebView. I am aware that WebView doesn't support displaying PDF normally so I am using the G-Drive URL extension suggested in other answers. Also, the Business team has demanded to open the PDF in our App itself so I can't fire an Intent to other PDF Viewer. I downloaded the PdfViewer library but it increased the APK size far beyond desire.
This URL is actually a GET request. Every time I hit the request, depending on the request parameters the server generates the PDF at runtime and returns it immediately without storing it on the server.
PDF URL:
"http://server_ip_number/pata/retail/v4/reports_pdf?search=Test&min_amount=0.0&max_amount=0.0" (can't disclose IP address for security reasons)
This request also demands some headers for auth, which I'll post below in detail.
This is what I am doing currently;
class AllUsersWebViewActivity : BaseActivity() {
private val pdfActualUrl = "https://drive.google.com/viewerng/viewer?embedded=true&url=http://server_ip_number/pata/retail/v4/reports_pdf?search=Test&min_amount=0.0&max_amount=0.0"
//This random dummy URL opens perfectly, it does not need any headers or GET params, just normal `loadUrl()` works.
private val workingDummyUrl = "https://drive.google.com/viewerng/viewer?embedded=true&url=https://mindorks.s3.ap-south-1.amazonaws.com/courses/MindOrks_Android_Online_Professional_Course-Syllabus.pdf"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_all_users_report_web_view)
wv_web.settings.javaScriptEnabled = true
wv_web.clearCache(true)
wv_web.loadUrl(URLEncoder.encode(pdfUrl, "ISO-8859-1"), mapOf( //map of necessary headers
"Authorization" to "Auth_TOKEN",
"VersionId" to "1.0.0",
"companyID" to "2",
"DeviceId" to "my_device_id",
"token" to "SECURE_TOKEN"
))
}
NOTE:
When I hit the above mentioned GET request with headers and params on PostMan it immediately downloads the PDF file.
I tried the same GET request with DownloadManager with all the headers and params the PDF file is downloaded successfully
But when I try it with WebView it just shows No Preview Available.
What am I doing wrong?
The headers that you are supplying, at most, will affect the behavior of Google's Web server for the https://drive.google.com/viewerng/viewer request. Google is not going to pass those along to some other server for http://server_ip_number/pata/retail/v4/reports_pdf.
I've been working with json for some time and the issue is the strings I decode are encoded as Latin-1 and I cannot get it to work as UTF-8. Because of that, some characters are shown incorrectly (ex. ' shown as ').
I've read a few questions here on stackoverflow, but they doesn't seem to work.
The json structure I'm working with look like this (it is from YouTube API):
...
"items": [
{
...
"snippet": {
...
"title": "Powerbeats Pro “Totally Wireless” Except when you need a wire",
...
}
}
]
I encode it with:
response = await http.get(link, headers: {HttpHeaders.contentTypeHeader: "application/json; charset=utf-8"});
extractedData = json.decode(response.body);
dataTech = extractedData["items"];
And then what I tried was changing the second line to:
extractedData = json.decode(utf8.decode(response.body));
But this gave me an error about wrong format. So I changed it to:
extractedData = json.decode(utf8.decode(response.bodyBytes));
And this doesn't throw the error, but neither does it fix the problem. Playing around with headers does neither.
I would like the data to be stored in dataTech as they are now, but encoded as UTF-8. What am I doing wrong?
Just an aside first: UTF-8 is typically an external format, and typically represented by an array of bytes. It's what you might send over the network as part of an HTTP response. Internally, Dart stores strings as UTF-16 code points. The utf8 encoder/decoder converts between internal format strings and external format arrays of bytes.
This is why you are using utf8.decode(response.bodyBytes); taking the raw body bytes and converting them to an internal string. (response.body basically does this too, but it chooses the bytes->string decoder based on the response header charset. When this charset header is missing (as it often is) the http package picks Latin-1, which obviously doesn't work if you know that the response is in a different charset.) By using utf8.decode yourself, you are overriding the (potentially wrong) choice being made by http because you know that this particular server always sends UTF-8. (It may not, of course!)
Another aside: setting a content type header on a request is rarely useful. You typically aren't sending any content - so it doesn't have a type! And that doesn't influence the content type or content type charset that the server will send back to you. The accept header might be what you are looking for. That's a hint to the server of what type of content you'd like back - but not all servers respect it.
So why are your special characters still incorrect? Try printing utf8.decode(response.bodyBytes) before decoding it. Does it look right in the console? (It very useful to create a simple Dart command line application for this type of issue; I find it easier to set breakpoints and inspect variables in a simple ten line Dart app.) Try using something like Wireshark to capture the bytes on the wire (again, useful to have the simple Dart app for this). Or try using Postman to send the same request and inspect the response.
How are you trying to show the characters. If may simply be that the font you are using doesn't have them.
just add the header : 'Accept': 'application/json; charset=UTF-8';
it worked for me
My header looks like :
final response = await http.get(url, headers: {
'Content-Type': 'application/json; charset=UTF-8',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
});
And the response is handled like:
Map<String, dynamic> data = json.decode(utf8.decode(response.bodyBytes));
I am trying to upload a file from andriod application, using Jquery to node.js using express..
My client side code is:
function uploadData(win) {
var padI = imagedata.length-1
while( '=' == imagedata[padI] ) {
padI--
}
var padding = imagedata.length - padI - 1
var user = load('user')
$.ajax({
url:'http://'+server+'/lifestream/api/user/'+user.username+'/upload',
type:'POST',
contentType: false,
processdata:false,
data:imagedata,
success:win,
error:function(err){
showalert('Upload','Could not upload picture.')
},
})
}
I have used post form without any content type because if i use multipart/form-data it says error about boundary ..
my server side code using node.js is:
function upload(req,res) {
var picid=uuid()
console.log('Got here..' + __dirname)
//console.log('Image file is here ' + req.files.file.path)
// console.log('local name: ' + req.files.file.name)
var serverPath = __dirname+'/images/' + picid+'.jpg'
fs.rename(
req.files.file.path,
serverPath,
function(error) {
if (error) {
console.log('Error '+error)
res.contentType('text/plain')
res.send(JSON.stringify({error: 'Something went wrong saving to server'}))
return;
}
// delete the /tmp/xxxxxxxxx file created during download
fs.unlink(req.files.file.path, function() { })
res.send(picid)
}
)
}
when the file comes to server, it gives an error of res.files.file is undefined ..
I have searched alot of forums, they say that res.files.file is only access when contenttype is multipart/form-data but then the boundary problem occurs
Any help on that is highly appreciated
Boundary is a special sequence of characters that separates your binary data.
You should submit MIME type as multipart/form-data, as well as set your imagedata to FormData() type (from your snippet it's not clear if it is FormData type).
Here are similar issues and solutions:
How to set a boundary on a multipart/form-data request while using jquery ajax FormData() with multiple files
jQuery AJAX 'multipart/form-data' Not Sending Data?
A great alternative to writing this code is to use filepicker.io This allows you to connect to yoru own s3 bucket. When the file is saved, you get back a callback with the S3 url, you can then simply pass that url to your node api, and save it. I have used this to avoid having to write extra server code for handling file uploads. Extra bonus, if you need to do this with images, and want users to be able to edit the images, you can use Aviary which allows an image to be edited locally, and you then get back another s3 url, that you can then save to your server..
Http request header:
Host: www.mysite.com
Content-Type: application/x-www-form-urlencoded
Cookie: bbuserid=XXX; bbpassword=YYY; bbsessionhash=ZZZ
Content-Length: 252
Http request body:
message=%E4%F6%F5%FC%E4%F6%F5%FC%E4%F6%F5%FC%E4%F6%F5%FC&securitytoken=XXX&do=postreply&t=483553
Working fine! Data posted to server gets decoded on the other end and user sees orginal message which is äöõüäöõüäöõüäöõü.
Now lets try to implement this excact example with JSoup:
//request body
Map<String, String> datamap = new HashMap<String, String>();
datamap.put(Session.SESSION_SECURITYTOKEN,"XXX");
datamap.put("message", URLEncoder.encode(finalText, "ISO-8859-1"));
datamap.put("do", "postreply");
datamap.put("t", "483553");
//make a post
Jsoup.connect(url)
.header("Content-Type","application/x-www-form-urlencoded")
.timeout(10000)
.cookie(Session.COOKIE_HASH_KEY,session.bbsessionhash)
.cookie(Session.COOKIE_PASSWORD_KEY,session.bbpassword)
.cookie(Session.COOKIE_USERID_KEY,session.bbuserid)
.data(datamap).post();
My message gets posted BUT it is not decoded by the server. So when user views the message he/she sees: %E4%F6%F5%FC%E4%F6%F5%FC%E4%F6%F5%FC%E4%F6%F5%FC
Note: I am doing the post request from Android and posting data to vBulletin forum software (replay to thread).
The problem: When I send the message with JSoup, server sees it like a plain text not a encoded text. How can I make the server to understand that the message parameter holds encoded text, not plain text?
Jsoup uses UTF-8 by default to URL-encode the query string. With the current API version, you cannot change it without rebuilding the source (it's the org.jsoup.helper.DataUtil#defaultCharset constant which is been used in org.jsoup.helper.HttpConnection class). Best what you can do is to post an issue report requesting the ability to preset the charset beforehand.
Until then, you could use HttpClient or URLConnection instead which allows for a more finer grained control over sending HTTP requests. You could finally feed its response as an InputStream to Jsoup#parse() method.
Update: if the target website supports it, you could try explicitly specifying the client's used charset in the Content-Type request header:
.header("Content-Type","application/x-www-form-urlencoded;charset=UTF-8")
Note that you should not use URLEncoder#encode() yourself; let Jsoup do its job.