How can I trigger download base on API response? - image

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()
})

Related

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

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));

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()
})
})

Save image from url to App in some folder like tmp,document for offline use

I want to save image once loaded URL, then save them in at some place like document or tmp folder and in offline mode to use saved images.
I have tried with react-native-fs, but did not succeed, it gives error.
you can save images from a url by converting the images to base64. Afterwhich, you can do anything with the image such rebuilding/writing the bytes to real image.
let try this.
import RNFetchBlob from 'rn-fetch-blob'
import Share from 'react-native-share'
import RNFS from 'react-native-fs'
import {Alert, Platform} from 'react-native'
const download = (url) => {
let dirs = RNFetchBlob.fs.dirs
try {
if (Platform.OS === 'android') {
const configOptions = { fileCache: true }
RNFetchBlob.config(configOptions)
.fetch('GET', url, {
'Authorization': '', //yourTokenIfHave
'Content-Type': '' // 'application/octet-stream'
})
.then(resp => {
return resp.readFile('base64')
})
.then(async base64Data => {
base64Data = `data:application/pdf;base64,` + base64Data
await Share.open({ url: base64Data })
// remove the image or pdf from device's storage
await RNFS.unlink(filePath)
})
} else {
RNFetchBlob
.config({
fileCache: true,
path: dirs.DocumentDir + `/${itemPDF.fileName}`
})
.fetch('GET', url, {
'Authorization': '',
'Content-Type': '' // 'application/octet-stream'
})
.then(async (res) => {
// the temp file path
if (res && res.path()) {
const filePath = res.path()
let options = {
type: 'application/pdf',
url: filePath
}
await Share.open(options)
await RNFS.unlink(filePath)
}
})
.catch((error) => {
console.log(error)
})
}
} catch (error) {
console.log('download: ', error)
}
}

React-native : response of fetch impossible to treat

Still learning on RN... I'm trying to use fetch() in react-native to get a specific data from my server, before opening a webpage in smartphone's browser.
Here is what I wrote :
openLink = () => { //Communicate to the server to get an unique key_id
this.state = {urlKey: 'text'}; //Initial state
var params = {
// Some params send by POST to authenticate the request...
};
var formData = new FormData();
for (var k in params) {
formData.append(k, params[k]);
}
fetch(Constants.URL.root+"mobile/authorize_view", {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({urlKey:responseJson.document_key}); //Getting the response, and changing the initial state (was 'text' previously)
})
.done();
var urlString = Constants.URL.upload + '/' + this.state.urlKey; // !!Problem : opening in browser with this.state.urlKey = text, and not document_key!!
Linking.canOpenURL(urlString).then(supported => {
if (supported) {
Linking.openURL(urlString);
} else {
console.log('Don\'t know how to open URI: ' + this.props.url);
}
});
}
Actually, as you can see, I ask for a specific key to my server (urlKey, that is returned in a JSON Object : responseJson.document_key).
Everything is running well in server's part, cause I put this generated document_key in my Database, and I can see it is put correctly.
The problem is in React-native part : the browser opens a webpage with this.state.urlKey as **text** which is the initial state that the function fetch should have turned into the document_key sent by server...
What am I missing ?
The fetch statement is asynchronous. Meaning when you call fetch then next line of execution not necessary the .then but is
var urlString = Constants.URL.upload + '/' + this.state.urlKey;
Note by this stage if .then isnt complete fetching the data your this.state.document_key will not be populated. Hence why you see the error
Instead move that code in the final then e.g:
openLink = () => { //Communicate to the server to get an unique key_id
this.state = {urlKey: 'text'}; //Initial state
var params = {
// Some params send by POST to authenticate the request...
};
var formData = new FormData();
for (var k in params) {
formData.append(k, params[k]);
}
fetch(Constants.URL.root+"mobile/authorize_view", {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({urlKey:responseJson.document_key}); //Getting the response, and changing the initial state (was 'text' previously)
//moved inside then
var urlString = Constants.URL.upload + '/' + this.state.urlKey; // !!Problem : opening in browser with this.state.urlKey = text, and not document_key!!
Linking.canOpenURL(urlString).then(supported => {
if (supported) {
Linking.openURL(urlString);
} else {
console.log('Don\'t know how to open URI: ' + this.props.url);
}
});
})
.done();
}

Resources