web-dev-qa-db-fra.com

Téléchargement de fichier rapide

J'ai un lien sur ma page au clic duquel je tente de générer un document PDF puis d'afficher l'invite "Ouvrir - Enregistrer" sur le navigateur.

Mon code HTML (composant reactjs) a le code ci-dessous où onclick appelle la fonction _getMyDocument qui appelle ensuite une méthode Webapi.

 <div className="row">
     <a href="#" onClick={this._getMyDocument.bind(this)}>Test Link</a>
 </div>  

_getMyDocument(e) {
            GetMyDocument(this.props.mydata).then(()=> {
   }).catch(error=> {

  });

Mon contrôleur a le code ci-dessous 

[HttpPost]
[Route("Generate/Report")]
public IHttpActionResult GetMyReport(MyData myData)
 {  
    byte[] myDoc = MyBusinessObject.GenerateMyReport(myData);
    var result = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new ByteArrayContent(myDoc)
        };
        result.Content.Headers.ContentDisposition =
            new ContentDispositionHeaderValue("attachment")
            {
                FileName = "MyDocument.pdf"
            };
        result.Content.Headers.ContentType =
            new MediaTypeHeaderValue("application/octet-stream");

        var response = ResponseMessage(result);

        return response;
  }

Actuellement, tout le code est exécuté mais je ne reçois pas le fichier PDF. Invite de téléchargement. Qu'est-ce que je fais mal ici?

Objet de réponse en cas de succès de l'appel ajax lokks comme ci-dessous

 enter image description here

16
San

Votre réponse du serveur semble bonne. La partie manquante est que vous ne gérez pas correctement cette réponse du côté client.

Supposons que votre objet URL de ressource ressemble à celui présenté ci-dessous dans js. (c'est-à-dire que vous connaissez déjà l'URL de la ressource. Si vous ne le connaissez pas encore, vous aurez besoin d'un appel séparé au serveur pour connaître l'URL du téléchargement.)

response.downloadUrl = app/media/fileId/document.pdf

Tout ce que vous devez faire est de définir, 

window.location = item.downloadUrl;

Cela obligera le navigateur à demander une ressource au serveur, la réponse du serveur must include Content-Disposition:attachment;. Le navigateur affichera la boîte de dialogue de téléchargement.

P.S. J'ai récemment travaillé sur une fonctionnalité similaire. Si tu as des questions, s'il te plait pose-les.

Lorsque vous souhaitez forcer le navigateur à afficher l'invite de téléchargement pour certains fichiers (ou ressources), vous devez inclure Content-Disposition:attachment; dans l'en-tête de la réponse (ce que vous avez déjà fait).

7
ScrapCode

Une méthode simple consiste à utiliser la méthode GET sur votre serveur et à recevoir vos données par des paramètres de requête.

Ensuite, dans votre application client, il vous suffit de créer un lien classique:

<a href="http://your-server.com/your-resource?param1=123&param2=456">Test Link</a>

Ou utilisez ce simple script js si vous souhaitez le gérer à partir de votre logique de script:

window.open("http://your-server.com/your-resource?param1=123&param2=456");
2
Thibaud Sowa

Votre problème est que la fonction GetMyDocument recevra le fichier PDF en tant que réponse du serveur et vous ne faites actuellement rien avec cette réponse. Vous devez gérer la réponse dans le rappel en cours. L'enregistrement de fichiers à partir de javascript n'est pas tout à fait simple. Je vous recommande donc d'utiliser une bibliothèque externe telle que filesaver.js pour vous aider.

Cela finira par ressembler à quelque chose comme ...

_getMyDocument(e) {
    GetMyDocument(this.props.mydata)
    .then((response)=> {
        const returnedFile = new Blob([response], { type: 'application/pdf'});
        saveAs(returnedFile);
    }).catch(error=> {

    });
0
Alex Young

Dans notre application (angulaire), nous devions créer une URL d'objet pour cela avec un code tel que:

WebApi:

result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(data);
result.Content.Headers.Add("Content-Type", "application/pdf");
result.Content.Headers.ContentDisposition =
                        new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
                        {
                            FileName = "FileNameHere"
                        };

return result;

javascript:

// HttpCall in here
// On SuccessResponse
    var file = new Blob([data], {
                    type: 'application/pdf'
                    });
    var fileURL = URL.createObjectURL(file);
// create an anchor and click on it.
    var ancorTag = document.createElement('a');
    ancorTag.href = fileURL;ancorTag.target = '_blank';
    ancorTag.download = 'CouponOrder.pdf';
    document.body.appendChild(ancorTag);
    ancorTag.click();
    document.body.removeChild(ancorTag);
0
Ermir Beqiraj

Créer une disposition de contenu et l'ajouter à l'en-tête de votre réponse 

var cd = new System.Net.Mime.ContentDisposition
{
    // for example foo.bak
    FileName = System.IO.Path.GetFileName(fileName),
    // always Prompt the user for downloading, set to true if you want 
    // the browser to try to show the file inline
    Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
0
croban