async function download(stuff) {
if (stuff.length > 1) {
//What do I do?
} else if (stuff.length === 1) {
const link= stuff[0];
axios({
url: `/link`,
method: "GET",
responseType: "blob", // important
}).then((response) => {
let url = window.URL.createObjectURL(new Blob([response.data]));
let a = document.createElement("a");
a.href = url;
a.download = "myFile.jpg"
a.click();
});
}
}
I use this and it works fine when I want to download a single file. But if stuff contains more elements, I would like to download them all. One after another doesn't work well, as the user has to confirm them separately. So, I would like to download them all together as a zip file. Is there a recommended method how to do that?
Related
I have an application that downloads a zip file in this way. It works regularly but when clicked, the download is performed in the background and the browser shows the actual download of the file only when the whole stream has been downloaded locally. So if the file takes 1 minute to download, the user doesn't understand what the site is doing. Is there any way to show a progress bar?
await axios({
url: sUrl,
method: "GET",
responseType: "blob" // important
})
.then(response => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", fname); //or any other extension
document.body.appendChild(link);
link.click();
this.setState({ downloading: false });
})
.catch(error => {
this.setState({ downloading: false });
message.warn("Errore: " + error.message);
return [];
});
Yes, you can achieve this by using onDownloadProgress method provided by axios package, check the below example :
await axios({
url: sUrl,
method: "GET",
responseType: "blob", // important
onDownloadProgress: (progressEvent) => {
let percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total); // you can use this to show user percentage of file downloaded
}
})
Axios package has both onDownloadProgress and onUploadProgress to show a progress bar during download or upload, have you tried them?
I recommend you to have a quick look at this Tutorial
axios.get("http://localhost:63542/api/v1/WorkInst",
{
responseType: 'arraybuffer',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/pdf'
}
})
.then((response) => {
console.log(response);
var blob = new Blob([response.data], {type: 'application/pdf'});
var downloadUrl = URL.createObjectURL(blob);
var a = document.createElement("a");
a.href= downloadUrl;
a.download = ("test.pdf");
a.click();
})
.catch((error) => console.log(error));
But instead of downloading, "Do you want to allow this website to open an app on your computer?" But it is working using google chrome and mozilla firefox. Badly need help on this
As far as I know, the Download attribute not support IE browser. So, in the IE and Edge browser, after getting the file data, you could use the msSaveOrOpenBlob method to download the file in IE and Edge browser, and in the Chrome or Firefox browser, you could create a hyperlink to download the file using the URL. More detail information, please check this sample:
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
//IE11 and the legacy version Edge support
console.log("IE & Edge");
let blob = new Blob([data], { type: "text/html" });
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {// other browsers
console.log("Other browsers");
var bl = new Blob([data], { type: "text/html" });
var a = document.createElement("a");
a.href = URL.createObjectURL(bl);
a.download = fileName;
a.hidden = true;
document.body.appendChild(a);
a.click();
}
I am trying to download a zip file from a Laravel API using Angular JS. I do not believe the issue is from Laravel.
Basically when the response comes and the download trigger is made it does not know its a .zip file, however the file itself is good. But then when I manually add the .zip extension in Angular JS in the file name the browser advises its a corrupt file.
If I do not add the extension, it downloads fine, and then if i rename the file with no extension in Windows and change it to test.zip it works perfectly as a zip file. This is how I know the data is good.
I have tried arraybuffer responseType and blob. With blob I am getting the download trigger, with arraybuffer nothing is happening (including no console errors).
Here is my JS controller code:
vm.downloadSelectedFiles = function() {
vm.selectedFiles = [];
angular.forEach(vm.fileDownloadList, function(value,index) {
if(value==1) {
vm.selectedFiles.push(index);
}
});
Data.downloadSelectedFiles(vm.selectedFiles,vm.stationIDToLookUp)
.then(function (data) {
var url = $window.URL || $window.webkitURL;
vm.fileUrl = url.createObjectURL(data.data);
var a = document.createElement("a");
a.href = vm.fileUrl;
a.download = 'test.zip';
//a.download = 'test';
a.click();
}).catch(function (err) {
});
}
Here is my JS service code
downloadSelectedFiles: function downloadSelectedFiles(selectedFiles,stationID) {
var apiBase = apiUrl + 'download-selected-files';
var config = {
//responseType: 'arraybuffer'
responseType: 'blob'
};
var data = {
selectedFiles: selectedFiles,
stationID: stationID
}
return $http.post(apiBase, data, config);
}
And just in case there is something relevant about the response from the API. Here is my Laravel code
public function downloadSelectedFiles(PublishDataRequest $requestData) {
return response()->file(storage_path() . '/app/files/test.zip');
}
Try setting the MIME type to application/zip:
Data.downloadSelectedFiles(vm.selectedFiles,vm.stationIDToLookUp)
.then(function (response) {
var blob = response.data;
var zipBlob = new Blob([blob], { type: "application/zip" });
var url = $window.URL || $window.webkitURL;
vm.fileUrl = url.createObjectURL(zipBlob);
var a = document.createElement("a");
a.href = vm.fileUrl;
a.download = 'test.zip';
//a.download = 'test';
a.click();
}).catch(function (response) {
console.log("ERROR", response);
throw response;
});
i have an Restful API i created using Laravel, this API like this:
http://127.0.0.1:8000/api/file/pdf/{id}
and this is my code for download:
public function pdfDownload($id){
$pdf = Cv::findOrfail($id);
return Storage::download('public/pdf/'.$pdf->pdf);
}
it is worked in postman, and also in browser, it is directly download the file,
but with react.js, it is not work, this my code in react:
pdfDownload = (id) => {
fetch(' http://127.0.0.1:8000/api/file/pdf/' + id, {
method: 'get',
headers: {
Accept: 'application/octet-stream',
'Content-Type': 'application/octet-stream'
}
}).then((res) => res.json());
};
and i call this function in button like this :
<Button color="primary" onClick={() => this.pdfDownload(data.id)}>
Download
</Button>
the id is corrected, i am ensure from this, my question is how can i download file when click this button.. Thans...
XHR calls can not trigger file download, the way browser handles it. You will have to mimic a file download using javascript code yourself, using something like below:
Reference
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.pdf');
document.body.appendChild(link);
link.click();
Or use File Saver package, if you don't mind an extra dependency.
FileSaver Npm
I have been trying to follow different posts on downloading a file sent from my Web API. So far I can get the file to come, it will open the download window and it will save. However, I cannot open it so something must be wrong somewhere.
Here is my AngularJS so far.
return $http({
url: State.Endpoint + "/api/account/picture",
method: "GET",
responseType: 'arrayBuffer'
}).then(function (data) {
var octetStreamMime = 'application/octet-stream';
var success = false;
var file = new Blob([data.data], {
type: "image/jpeg"
});
var fileUrl = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileUrl;
a.target = "_blank";
a.download = "myFile.jpg";
document.body.appendChild(a);
a.click();
});
That will make my successfully download the image for me. However, this doesn't let me open the file so either something is still wrong on client side or server side.
Server Side Code:
[Route("picture")]
[HttpGet]
public HttpResponseMessage GetPictureBlob()
{
HttpResponseMessage response = null;
var localFilePath = HttpContext.Current.Server.MapPath("~/Content/Images/demo.jpg");
if (!File.Exists(localFilePath))
{
response = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{
var fStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read);
// Serve the file to the client
response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(fStream)
};
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = Path.GetFileName(fStream.Name)
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
//response.Headers.Add("content-type", "application/octet-stream");
}
return response;
}
The provided value 'arrayBuffer' is not a valid enum value of type XMLHttpRequestResponseType.
Use arraybuffer all lowercase:
$http({
url: State.Endpoint + "/api/account/picture",
method: "GET",
//responseType: 'arrayBuffer'
//USE arraybuffer lowercase
responseType: 'arraybuffer'
//OR
//responseType: 'blob'
})
When the responseType is not valid, the XHR API defaults to decoding the response as UTF-8. This corrupts binary files such as JPEG images.
For more information, see MDN XHR Web API - responseType.
Creating a Download Button
Instead of creating a <a download></a> element with JavaScript DOM manipulation, consider using the AngularJS framework.
This is an example of a Download button that becomes active after the data is loaded from the server:
<a download="data_{{files[0].name}}" xd-href="data">
<button ng-disabled="!data">Download</button>
</a>
The xdHref Directive
app.module("myApp").directive("xdHref", function() {
return function linkFn (scope, elem, attrs) {
scope.$watch(attrs.xdHref, function(newVal) {
if (newVal) {
elem.attr("href", newVal);
}
});
};
});
The DEMO on PLNKR.
I've done the very same thing with this code, where:
data: Data received from server
format: data format, it must be one of https://developer.mozilla.org/en-US/docs/Web/API/Blob/type
name: your file's name
Code:
function downloadBlobFile(data, format, name) {
// format must be one of https://developer.mozilla.org/en-US/docs/Web/API/Blob/type
var file = new Blob([data], {type: 'application/' + format});
file.lastModified = new Date();
file.name = name + '.' + format.trim().toLowerCase();
// guarantee IE compatibility
if($window.navigator && $window.navigator.msSaveOrOpenBlob) {
$window.navigator.msSaveOrOpenBlob(file, file.name);
}
//other web browser
else {
/**
* Because this technology's specification has not stabilized, compatibility has been
* checked here: https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL#Browser_compatibility
*/
var fileURL = $window.URL.createObjectURL(file);
/* trick for downloading the file, borrowed from:
http://stackoverflow.com/questions/19327749/javascript-blob-filename-without-link
*/
var a = angular.element("<a style='display: none;'/>").attr("href", fileURL).attr("download", file.name);
angular.element(document.body).append(a);
a[0].click();
$window.URL.revokeObjectURL(fileURL);
a.remove();
}
}
var a = document.createElement("a"); //Create <a>
a.href = "data:image/png;base64," + ImageBase64;
a.download = "Image.png"; //File name Here
a.click(); //Downloaded file
Simplest way worked for me