2017-08-23 1 views
0

Je reçois une réponse web via une API qui convertit le fichier (dans ce cas, les présentations Powerpoint en PDF). Je reçois la réponse dans une chaîne, mais quand j'enregistre cette chaîne dans un fichier ou un flux (qui finit par être sauvegardé dans un fichier), je me retrouve toujours avec un fichier vide, sa taille est toujours bien au-dessus 0 octets cependant.Contenu PDF renvoyé dans la réponse Web, comment enregistrer localement?

est ici la classe qui appelle l'API:

public class CloudConvert 
{ 

    private string apiKey; 
    private static object ProcessResponse; 

    public CloudConvert(string apiKey) 
    { 
     this.apiKey = apiKey; 
    } 

    public async Task<string> Convert(string inputFormat, string outputFormat, string fileUrl) 
    { 
     var processUrl = await CreateProcess(inputFormat, outputFormat); 
     return await Upload(processUrl, fileUrl, outputFormat); 
    } 

    private async Task<string> CreateProcess(string inputFormat, string outputFormat) 
    { 
     var request = new 
     { 
      apikey = apiKey, 
      inputformat = inputFormat, 
      outputformat = outputFormat 
     }; 

     var json = await PostJson("https://api.cloudconvert.com/process", request); 

     dynamic obj = JObject.Parse(json); 
     ProcessResponse = obj; 
     return "https:" + obj.url; 
    } 

    private static async Task<string> Upload(string processUrl, 
     string fileUrl, string outputFormat) 
    { 
     var request = new 
     { 
      input = "download", 
      file = fileUrl, 
      outputformat = outputFormat, 
      download = "false", 
      wait = "true", 
      save = "false" 
     }; 

     return await PostJson(processUrl, request); 
    } 


    private static async Task<string> PostJson(string url, object data) 
    { 
     var parameters = JsonConvert.SerializeObject(data); 

     using (var wc = new WebClient()) 
     { 
      wc.Headers[HttpRequestHeader.ContentType] = "application/json"; 

      try 
      { 
       return await wc.UploadStringTaskAsync(url, "POST", parameters); 
      } 
      catch (WebException ex) 
      { 
       return string.Empty; 
      } 
     } 
    } 

} 

Et comment je l'invoque:

Task<string> task = Task.Run(async() => 
{ 
    return await cloudConvert.Convert("ppt", "pdf", "http://host.com/myfile.ppt"); 
}); 

//I have the PDF in the response, as a string. 
var pdfContent = task.Result; 

//I think it's here that I'm not handling the resulting string 
//properly, ending in a blank file. I've tried writing it to a local file as well, same issue. 
using (MemoryStream stream = new MemoryStream()) 
{ 
    StreamWriter writer = new StreamWriter(stream); 
    writer.Write(pdfContent); 
    writer.Flush(); 
    stream.Seek(0, SeekOrigin.Begin); 
    //This below is something that saves to an Azure storage container... 
    //filePath = fileStorage.SaveFile($"{fileGeneratedName}.pdf", stream); 

    //But this fails as well. Blank file 
    using (FileStream fs = new FileStream(@"c:\tmp\output.pdf", FileMode.OpenOrCreate)) 
    { 
     stream.CopyTo(fs); 
     fs.Flush(); 
    } 
} 

Ainsi, peu importe la façon dont je suis en train de sauver le contenu retourné, il semble mon encodage est faux. J'ai remarqué que le fichier vide résultant a toujours le même nombre de pages que la présentation PowerPoint en entrée.

Des idées?

+0

PDF sont des fichiers binaires et ne peut pas être représenté par cordes. Ou vous recevez le contenu avec le format incorrect (chaîne au lieu de binaire) ou les données renvoyées sont codées en base64. Reportez-vous à la documentation de service pour connaître le problème. – Gusman

+0

@Gusman 'pdfContent' semble contenir des données similaires aux données que je verrais si j'ouvrais un PDF fonctionnel dans Notepad ++. (En-tête '% PDF-1.7' par exemple). –

+0

Ensuite, vous le lisez en tant que chaîne et c'est incorrect, vous devez le lire en tant que données binaires ou vous allez corrompre le contenu. – Gusman

Répondre

0

Demandez à votre fonction de conversion retourner un HttpResponseMessage:

public async Task<HttpResponseMessage> convert() 

faire votre conversion en, par exemple, un flux de mémoire, puis:

var result = new HttpResponseMessage(HttpStatusCode.OK) 
{ 
    Content = new ByteArrayContent(outStream.GetBuffer(),0,(int)outStream.Length) 
}; 
result.Content.Headers.ContentDisposition = 
     new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") 
     { 
       FileName = fname 
     }; 
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); 
return result;