Window.open() does not work on safari IOS 16 - async-await

I am using JavaScript window.open() method to open new window inside of async function, it works well in IE, Firefox, chrome, brave but not working in safari for mobile.
fetch('http://example.com/movies.json')
.then((response) =>
if(response){
const blob = new Blob([response], { type: "application/pdf" });
const url = window.URL.createObjectURL(blob)
window.open(url)
}
)
.catch((error) => console.log(error));

I found one solution for above problem for all browsers with all OS (IOS, android and windows, linux).
It's working for me.
function downloadBlobFile(blob, fileName) {
//Check the Browser type and download the File.
const isIE = !!document.documentMode;
if (isIE) {
window.navigator.msSaveBlob(blob, fileName);
} else {
const url = window.URL || window.webkitURL;
const link = url.createObjectURL(blob);
const a = document.createElement("a");
a.setAttribute("download", fileName);
a.setAttribute("href", link);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
}
fetch('http://example.com/movies.json')
.then((response) =>
if(response){
const blob = new Blob([response], { type: "application/octetstream" });
downloadBlobFile(blob, "test.pdf")
}
)
.catch((error) => console.log(error));

Related

How can I trigger download base on API response?

I called an API to get the QR Code, I got the response back and was able to display it on the DOM as whatever the type user selected, but now I need to download it
I tried
axios
.post(window.URL, body, { responseType: 'arraybuffer' })
.then((response) => {
console.log('get-serial', response.data)
const base64 = btoa(new Uint8Array(response.data).reduce((data, byte) => data + String.fromCharCode(byte), ''))
//download
var img = new Image()
img.src = 'data:image/jpeg;base64, ' + base64
return img
})
.catch((err) => {
console.log('Something went wrong: ', err)
})
I don't see any image download when that run.
This works perfectly;
axios
.post(window.URL, body, { responseType: 'arraybuffer' })
.then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', 'filename.ext')
document.body.appendChild(link)
link.click()
})

Why does my download feature (created using Vue JS and Laravel) result in corrupted files?

I'm currently working on a download feature which allows users to download the files (of all types) that they've uploaded. The downloading feature works (as in the files appear in my downloads folder and the file type is registered in the image that appears next to the file name), however for some reason all of the files I've downloaded are deemed corrupted or of the wrong format.
Axios request (inside a method):
downloadFile(file) {
axios.get(window.routes.files.download.replace("_id_", file.id), {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/vnd.ms-excel'
}
})
.then(function(response){
if (!window.navigator.msSaveOrOpenBlob){
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', file.name);
document.body.appendChild(link);
link.click();
}else{
const url = window.navigator.msSaveOrOpenBlob(new Blob([response.data]),file.name);
}
console.log(response.data);
})
.catch(function(error){
console.error(error);
if (!!error.response) console.log(error.response);
});
},
Laravel route:
Route::get('files/{file}', 'FileController#downloadSomeFile')->name('files.download');
My controller:
public function downloadSomeFile($id)
{
$downloadFile = File::find($id);
Storage::download(str_replace('/File', '', $downloadFile->path));
}
Is there a way to fix it?
Below is an example of the message I get when I try to open the downloaded file:
You have to set a responseType in your ajax if you want to download a non text file.
downloadFile(file) {
axios.get(window.routes.files.download.replace("_id_", file.id), {
headers: {
'Accept': 'application/vnd.ms-excel'
},
responseType: 'arraybuffer' //<-- here
})
.then(function(response){
if (!window.navigator.msSaveOrOpenBlob){
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', file.name);
document.body.appendChild(link);
link.click();
}else{
const url = window.navigator.msSaveOrOpenBlob(new Blob([response.data]),file.name);
}
console.log(response.data);
})
.catch(function(error){
console.error(error);
if (!!error.response) console.log(error.response);
});
},

How to take a photo and upload it to the server with Nativecript-camera

I am new to Nativescript Vue development, I am trying to take a photo and send it to the server. My code works fine on Android, but when I run on iOS, errors occur, the image doesn’t even paste onto the page and doesn’t upload to the server.
import * as camera from "nativescript-camera";
import * as bghttp from "nativescript-background-http";
const firebase = require("nativescript-plugin-firebase");
var session = bghttp.session("image-upload");
takePicture() {
camera.requestPermissions()
.then(() => {
camera.takePicture({ width: 300, height: 300, keepAspectRatio: true, saveToGallery:true })
.then(imageAsset => {
this.img = imageAsset.android;
})
.catch(e => {
console.log('error:', e);
});
})
.catch(e => {
console.log('Error requesting permission');
});
}
upload() {
var file = this.img;
var url = "https://bocorp.ru/assets/mobileNewOrder.php";
var name = file.substr(file.lastIndexOf("/") + 1);
// upload configuration
var bghttp = require("nativescript-background-http");
var session = bghttp.session("image-upload");
var request = {
url: url,
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
"File-Name": name,
},
content: JSON.stringify({
Title: title
}),
description: "Uploading " + name
};
var task = session.uploadFile(file, request);
I understand that another code should be used in "this.img = imageAsset.android;" but I don’t understand how can I get a photo from the Iphone camera. I will be glad to any prompt
We save our images to the device, and then upload later as a multipart upload. You might be able to skip the file saving part, but it does allow us to keep from reading in the entire image for uploading later in our app flow (I guess if you already have the image source for display you could reuse it for upload on the same page).
Hope you find this helpful.
const imageSource = require('tns-core-modules/image-source')
// ...
camera.takePicture(cameraOpts)
.then(imageAsset => {
return imageSource.fromAsset(imageAsset)
})
.then(imageSource => {
let pathDest = '/path/on/device' // you define
console.log(`Created image source with width=${imageSource.width} height=${imageSource.height} at ${pathDest}`)
imageSource.saveToFile(pathDest, 'jpg', 50)
return pathDest // save this to look up later
})
Then when we need to upload
const mime = require('mime-types')
import * as bghttp from 'nativescript-background-http'
...
let session = bghttp.session('image-upload')
let request = {
url: 'https://yourendpoint.com/here',
method: 'POST',
androidAutoDeleteAfterUpload: true,
headers: {
'Content-Type': 'application/octet-stream',
}
}
// photoPath is known somehow. We use Vuex, but somehow it makes it to this page
let params = [
{ name: 'photo1', filename: photoPath, mimeType: mime.lookup(photoPath) }
]
return new Promise((resolve, reject) => {
let task = session.multipartUpload(params, request)
task.on('error', (e) => {
reject(e)
})
task.on('complete', res => {
resolve()
})
})

Image uploaded incorrectly to s3 using amplify Storage (React Native - Expo - Amplify)

I'm trying to upload an image to s3 with Amplify Storage API.
I use the EXPO imagePicker to upload the image from the phone to React-Native, and it's displayed correctly.
Then I upload it to s3 with amplify Storage.put, and it reaches the correct folder in s3, with the proper filename that I gave it and with public access I provided (to the image and the bucket itself).
BUT if I try to open the photo uri in s3 it doesn't display. When I inspect the browser it shows this error on console:
If I paste in the browser the uri I get from Storage.get , i get this error:
My code is the following (I helped myself with this tutorial https://blog.expo.io/how-to-build-cloud-powered-mobile-apps-with-expo-aws-amplify-2fddc898f9a2):
_handleImagePicked = async (pickerResult) => {
const s3path = 'fotos_cdcc/' + '186620' + '/'
const imageName = '186620_4' + '.jpeg'
const key = s3path + imageName
const fileType = pickerResult.type;
const access = { level: "public", contentType: 'image/jpg' };
const imageData = await global.fetch(pickerResult.uri)
const blobData = await imageData.blob()
try {
await Storage.put(
key,
blobData,
access,
fileType
).then(result => console.log(result))
} catch (err) {
console.log('error: ', err)
}
}
The pickerResult has this form:
Object {
"cancelled": false,
"height": 750,
"type": "image",
"uri": "file:///var/mobile/Containers/Data/Application/021D6288-9E88-4080-8FBF-49F5195C2073/Library/Caches/ExponentExperienceData/%2540anonymous%252Fcaballos-app-dd2fa92e-4625-47e7-940e-1630e824347a/ImagePicker/D9EE1F24-D840-457F-B884-D208FFA56892.jpg",
"width": 748,
}
I tried making the bucket and the photo public in s3, but the error persists.
Any ideas?
Thanks in advance!
Maybe this is not an issue with aws-amplify, instead with fetch and blob. Can you try this?
function urlToBlob(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onerror = reject;
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
resolve(xhr.response);
}
};
xhr.open('GET', url);
xhr.responseType = 'blob'; // convert type
xhr.send();
})
}
Then instead of
const imageData = await global.fetch(pickerResult.uri)
const blobData = await imageData.blob()
Try
const blobData = await urlToBlob(pickerResult.uri)
Please find full discussion https://github.com/expo/firebase-storage-upload-example/issues/13

File Image size increases while uploading to firebase through expo image picker react native using XMLHttpRequest

I am facing a very strange issue that my Image size increases while uploading to firebase.
I have logged the file size before uploading, it is showing the same size but after uploading the file size gets increased. Also the image is not corrupted. Please help..
Uploading to firebase code :
async uploadImageAsync(uri, passedParameter, ItemName) {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function(e) {
console.log(e);
reject(new TypeError("Network request failed"));
};
xhr.responseType = "blob";
xhr.open("GET", uri, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child("CategoryDescription" + "/" + passedParameter + "/" + ItemName);
const snapshot = await ref.put(blob);
blob.close();
const downloadUrl = await snapshot.ref.getDownloadURL();
return downloadUrl;
}
**Pick Image code : **
async _pickImage() {
const { CAMERA, CAMERA_ROLL } = Permissions;
const permissions = {
[CAMERA]: await Permissions.askAsync(CAMERA),
[CAMERA_ROLL]: await Permissions.askAsync(CAMERA_ROLL)
};
if (
permissions[CAMERA].status === "granted" &&
permissions[CAMERA_ROLL].status === "granted"
) {
var pickerResult = await ImagePicker.launchImageLibraryAsync({
quality: 0.1
});
if (!pickerResult.cancelled) {
console.log(pickerResult);
this.setState({
itemImage: pickerResult.uri
});
** On button pressed code**
handleConfirmAddItems = () => {
var passedParameter = this.params.item.key;
const { ItemName, ItemPrice, ItemDesc, ItemWeight, itemImage } = this.state;
{
itemImage !== "" &&
this._handleImagePicked(itemImage, passedParameter, ItemName);
}
writeUrlToDB(
itemImage,
passedParameter,
ItemName,
ItemDesc,
ItemPrice,
ItemWeight
);
}
};
** handle image picked **
async _handleImagePicked(itemImage, passedParameter, ItemName) {
try {
const uploadUrl = await this.uploadImageAsync(
itemImage,
passedParameter,
ItemName
);
this.setState({ itemImage: uploadUrl });
console.log("itemIma", uploadUrl);
} catch (e) {
console.log(e);
alert("Upload failed, sorry :(");
}
}
Please help.. I am in great stress
A bug in Image picker.. This is the issue in the case of iOS Simulator, in Android device its working fine : )

Resources