J'ai créé une application dans Angular JS pour le téléchargement d'un classeur Excel via $ http post.
Dans le code ci-dessous, je passe les informations sous la forme de JSON et les envoie au serveur REST service Web (Java) via un angular $ http post. Le service Web utilise les informations du JSON et génère un classeur Excel. Dans la réponse contenue dans le corps de succès de $ http post, je reçois des données binaires dans cette variable data, mais sais pas comment le convertir et le télécharger en fichier Excel.
Quelqu'un peut-il me dire s'il vous plaît une solution pour convertir le fichier binaire en fichier Excel et le télécharger?
Mon code est comme donné ci-dessous:
$http({
url: 'myweb.com/myrestService',
method: "POST",
data: json, //this is your json data string
headers: {
'Content-type': 'application/json'
}
}).success(function (data, status, headers, config) {
// Here i'm getting Excel sheet binary datas in 'data'
}).error(function (data, status, headers, config) {
});
Cela peut être fait via le navigateur, en utilisant blob
. Notez le responseType
et le code dans la promesse success
.
$http({
url: 'your/webservice',
method: "POST",
data: json, //this is your json data string
headers: {
'Content-type': 'application/json'
},
responseType: 'arraybuffer'
}).success(function (data, status, headers, config) {
var blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}).error(function (data, status, headers, config) {
//upload failed
});
objectUrl
que les gens auraient pu bloquerLe code côté serveur dans PHP). J'ai testé ceci avec un aspect similaire à celui-ci. Je suis sûr que vous pouvez définir des en-têtes similaires en Java:
$file = "file.xlsx";
header('Content-disposition: attachment; filename='.$file);
header('Content-Length: ' . filesize($file));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Pragma: public');
echo json_encode(readfile($file));
Les navigateurs rendent plus difficile la sauvegarde des données de cette façon. Une bonne option consiste à utiliser filesaver.js . Il fournit une implémentation multi-navigateurs pour saveAs
, et il devrait remplacer une partie du code de la promesse success
ci-dessus.
Voici comment vous le faites:
$http({ url: 'your/webservice', method: 'POST', responseType: 'arraybuffer', data: json, //this is your json data string headers: { 'Content-type': 'application/json', 'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' } }).success(function(data){ var blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); saveAs(blob, 'File_Name_With_Some_Unique_Id_Time' + '.xlsx'); }).error(function(){ //Some error log });
Pointe! Ne mélangez pas "et", tenez-vous-en à toujours utiliser ", dans un environnement professionnel, vous devrez passer la validation js, par exemple, jshint. Même chose pour utiliser === et non ==, etc., mais c'est un autre sujet :)
Je mettrais la sauvegarde Excel dans un autre service, de sorte que vous avez une structure propre et que le message est dans un service approprié. Je peux faire un violon JS pour vous, si mon exemple ne fonctionne pas. Ensuite, j'aurais aussi besoin de quelques données JSON de votre part que vous utiliseriez comme exemple complet.
Joyeux codage .. Eduardo
Téléchargez la réponse du serveur sous forme de tampon de tableau. Stockez-le en tant que blob en utilisant le type de contenu du serveur (qui devrait être application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
):
var httpPromise = this.$http.post(server, postData, { responseType: 'arraybuffer' });
httpPromise.then(response => this.save(new Blob([response.data],
{ type: response.headers('Content-Type') }), fileName));
Enregistrez le blob sur le périphérique de l'utilisateur:
save(blob, fileName) {
if (window.navigator.msSaveOrOpenBlob) { // For IE:
navigator.msSaveBlob(blob, fileName);
} else { // For other browsers:
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
window.URL.revokeObjectURL(link.href);
}
}
A travaillé pour moi -
$scope.downloadFile = function () {
Resource.downloadFile().then(function (response) {
var blob = new Blob([response.data], { type: "application/pdf" });
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
},
function (error) {
debugger;
});
};
Qui appelle les suivants de mon usine de ressources
downloadFile: function () {
var downloadRequst = {
method: 'GET',
url: 'http://localhost/api/downloadFile?fileId=dfckn4niudsifdh.pdf',
headers: {
'Content-Type': "application/pdf",
'Accept': "application/pdf"
},
responseType: 'arraybuffer'
}
return $http(downloadRequst);
}
Assurez-vous que votre API définit également le type de contenu de l'en-tête -
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
À ma connaissance, il n’existe aucun moyen de déclencher la fenêtre de téléchargement de votre navigateur à partir de Javascript. La seule façon de le faire est de rediriger le navigateur vers une URL qui diffuse le fichier dans le navigateur.
Si vous pouvez modifier votre service REST, vous pourrez peut-être le résoudre en modifiant la demande POST ne répond pas avec le fichier binaire, mais avec une URL vers ce fichier. Vous obtiendrez l’URL en Javascript au lieu des données binaires, et vous pourrez rediriger le navigateur vers cette URL, ce qui devrait provoquer le téléchargement sans quitter la page d’origine.
Réponse n ° 5 a fonctionné pour moi, suggestion au développeur qui fait face à un problème similaire.
//////////////////////////////////////////////////////////
//Server side
//////////////////////////////////////////////////////////
imports ***
public class AgentExcelBuilder extends AbstractExcelView {
protected void buildExcelDocument(Map<String, Object> model,
HSSFWorkbook workbook, HttpServletRequest request,
HttpServletResponse response) throws Exception {
//poi code goes here ....
response.setHeader("Cache-Control","must-revalidate");
response.setHeader("Pragma", "public");
response.setHeader("Content-Transfer-Encoding","binary");
response.setHeader("Content-disposition", "attachment; filename=test.xls");
OutputStream output = response.getOutputStream();
workbook.write(output);
System.out.println(workbook.getActiveSheetIndex());
System.out.println(workbook.getNumberOfSheets());
System.out.println(workbook.getNumberOfNames());
output.flush();
output.close();
}//method buildExcelDocument ENDS
//service.js at angular JS code
function getAgentInfoExcel(workgroup,callback){
$http({
url: CONTEXT_PATH+'/rest/getADInfoExcel',
method: "POST",
data: workgroup, //this is your json data string
headers: {
'Content-type': 'application/json'
},
responseType: 'arraybuffer'
}).success(function (data, status, headers, config) {
var blob = new Blob([data], {type: "application/vnd.ms-Excel"});
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}).error(function (data, status, headers, config) {
console.log('Failed to download Excel')
});
}
////////////////////////////////in .html
<div class="form-group">`enter code here`
<a href="javascript:void(0)" class="fa fa-file-Excel-o"
ng-click="exportToExcel();"> Agent Export</a>
</div>
Vous pouvez également adopter une approche alternative: vous n'avez pas besoin d'utiliser $ http, vous n'avez pas besoin de bibliothèques supplémentaires et cela devrait fonctionner dans n'importe quel navigateur.
Placez simplement un formulaire invisible sur votre page.
<form name="downloadForm" action="/MyApp/MyFiles/Download" method="post" target="_self">
<input type="hidden" name="value1" value="{{ctrl.value1}}" />
<input type="hidden" name="value2" value="{{ctrl.value2}}" />
</form>
Et placez ce code dans votre angular contrôleur.
ctrl.value1 = 'some value 1';
ctrl.value2 = 'some value 2';
$timeout(function () {
$window.document.forms['downloadForm'].submit();
});
Ce code publiera vos données sur/MyApp/MyFiles/Download et vous recevrez un fichier dans votre dossier Téléchargements.
Cela fonctionne avec Internet Explorer 10.
Si un formulaire HTML conventionnel ne vous permet pas de publier votre objet complexe, vous avez deux options:
1. Stringify votre objet et le mettre dans l'un des champs de formulaire sous forme de chaîne.
<input type="hidden" name="myObjJson" value="{{ctrl.myObj | json:0}}" />
2. Considérons les formulaires HTML JSON: https://www.w3.org/TR/html-json-forms/
J'ai créé un service qui le fera pour vous.
Passer dans un standard $http
objet, et ajouter des paramètres supplémentaires.
1) Un paramètre "type". Spécifier le type de fichier que vous récupérez. La valeur par défaut est: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
2) Un paramètre "fileName". Cela est nécessaire et devrait inclure l'extension.
Exemple:
httpDownloader({
method : 'POST',
url : '--- enter the url that returns a file here ---',
data : ifYouHaveDataEnterItHere,
type : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // this is the default
fileName : 'YourFileName.xlsx'
}).then(res => {}).catch(e => {});
C'est tout ce dont vous avez besoin. Le fichier sera téléchargé sur le périphérique de l'utilisateur sans fenêtre contextuelle.
Voici le dépôt Git: https://github.com/stephengardner/ngHttpDownloader