WebAPI parsuje zwracany plik jako json

0

Witam.
Nie wiem czy to dobry dział, bo i webmastering i C#, najwyżej przenieście.
Piszę seflhosted API w C# i natknąłem się na problem ze zwracaniem pliku. Wyczytałem gdzieś w internetach jak to zrobić i przerobiłem to pod siebie:

        public HttpResponseMessage GetWydrukDokumentu([FromUri]string numer)
        {
            FileStream fs;
            string trnId = SQL.GetData(Queries.DokumentIdQuery(numer)).Rows[0]["TrN_TrNId"].ToString();
            string file = WykonajWydrukDomyslnyFaktury(op, haslo, firma, hPar, trnId);

            fs = File.OpenRead(file);
            HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
            response.Content = new StreamContent(fs);
            response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = file;
            response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");

            return response;
        }

Problem polega na tym, że ten return jest zwracany jako json. Jak mu powiedzieć, że ma tego nie robić?

0

json czyli co konkretnie? Jak to pobierasz ?

0

WebAPI automatycznie robi json ze zwracanych obiektów. Nie trzeba robić JsonConvert itp. Co powinienem zrobić, aby API mi tego nie parsowało na json tylko faktycznie zwróciło po stronie klienta plik .pdf?

0
AdamWox napisał(a):

WebAPI automatycznie robi json ze zwracanych obiektów. Nie trzeba robić JsonConvert itp. Co powinienem zrobić, aby API mi tego nie parsowało na json tylko faktycznie zwróciło po stronie klienta plik .pdf?

Przy zwracaniu w metodzie IActionResult ja zwracam zipa w taki sposób:

return PhysicalFile(temporaryZIPDirectory + temporaryZIPFile, "application/zip", temporaryZIPFile);
0

Poprawiłem kod po twoją sugestię:

        public Microsoft.AspNetCore.Mvc.IActionResult GetWydrukDokumentu([FromUri]string numer)
        {
            FileStream fs;
            string trnId = SQL.GetData(Queries.DokumentIdQuery(numer)).Rows[0]["TrN_TrNId"].ToString();
            string file = WykonajWydrukDomyslnyFaktury(op, haslo, firma, hPar, trnId);

            fs = File.OpenRead(file);
            Microsoft.AspNetCore.Mvc.PhysicalFileResult f = new Microsoft.AspNetCore.Mvc.PhysicalFileResult(file, "application/pdf");
            f.FileDownloadName = $"faktura_{trnId}.pdf";

            return f;
        }

Zwraca mi jsona w postaci:

{
   FileName: "C:\Users\tron\source\repos\API\API\bin\x86\Debug\Dokument_64.pdf", 
   ContentType: "application/pdf",
   FileDownloadName: "faktura_64.pdf", 
   LastModified: null, 
   EntityTag: null
}
0

Ja w ASP.NET Core mam coś takiego:

[Produces("octet/binary")]
[HttpGet("{id}")]
public IActionResult Firmware(int id)
{
	// nieistotne

	if (System.IO.File.Exists(path))
	{
		return base.File(System.IO.File.ReadAllBytes(path), "octet/binary");
	}
	else
		return NotFound();
}
0

Nie mam u siebie File(), ponieważ to jest SelfHosted API, które tak na prawdę jest aplikacją winforms. Mogę zwrócić ręcznie FileStreamResult ale dostaję błędy po stronie klienta:

error:
ExceptionMessage: "Error getting value from 'ReadTimeout' on 'System.IO.FileStream'."
ExceptionType: "Newtonsoft.Json.JsonSerializationException"
InnerException: {Message: "An error has occurred.", 
ExceptionMessage: "Limity czasu nie są obsługiwane dla tego strumienia.", 
ExceptionType: "System.InvalidOperationException", 
StackTrace: "   
w System.IO.Stream.get_ReadTimeout()
w GetR…tion.DynamicValueProvider.GetValue(Object target)"}
Message: "An error has occurred."
StackTrace:"   
w Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)
w Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
w Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
w Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) 
w Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
w Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
w Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
w Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)   
w System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)
w System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)
w System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)
w System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
--- Koniec śladu stosu z poprzedniej lokalizacji, w której wystąpił wyjątek ---
w System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
w System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
w System.Net.Http.HttpContent.<LoadIntoBufferAsyncCore>d__49.MoveNext()
--- Koniec śladu stosu z poprzedniej lokalizacji, w której wystąpił wyjątek ---
w System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
w System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
w System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__27.MoveNext()"
0

A której wersji Ty w ogóle używasz asp.net web api czy może asp.net core?
Bo to co wkleiłeś w pierwszym poście jest poprawnym kodem dla asp.net web api.
A to co wkleił Biały Mleczarz jest poprawnym kodem dla asp.net core.
Oba działają, więc dobrze by było byś wstawił cały ten kontroler, ale tylko z tą jedną metoda, bo mam wrażenie że wymieszałeś elementy z dwóch różnych technologii ;)

0

Chyba asp.net web api. To, które przychodzi wraz z Microsoft.Owin

using NIP24;
using OptimoAPI.Classes;
using OptimoAPI.Models;
using System.Data;
using System.IO;
using System.Web.Http;

public class OgolneController : ApiController
{
      public Microsoft.AspNetCore.Mvc.IActionResult GetWydrukDokumentu([FromUri]string numer)
      {
         FileStream fs;
         string trnId = SQL.GetData(Queries.DokumentIdQuery(numer)).Rows[0]["TrN_TrNId"].ToString();
         string file = WykonajWydrukDomyslnyFaktury(op, haslo, firma, hPar, trnId);
         Microsoft.AspNetCore.Mvc.FileContentResult f = new Microsoft.AspNetCore.Mvc.FileContentResult(File.ReadAllBytes(file), "octet/binary");
         f.FileDownloadName = $"faktura_{trnId}.pdf";

         return f;
      }
}
0

Dostaje błąd. Treść jest bardzo długa więc wrzucę screena

0
AdamWox napisał(a):

Dostaje błąd. Treść jest bardzo długa więc wrzucę screena

To konsumujesz z jakiegoś javascriptu?
wklej sobie w przeglądarkę tą Twoją ściężke :
http://192.168.0.113:9000/tron/ogolne/getwydrukdokumentu?numer=FA/1/2018
a później usuń nazwę metody
http://192.168.0.113:9000/tron/ogolne/?numer=FA/1/2018
i zobacz różnicę :)

0

Angular

  baseAddress:string = 'http://192.168.0.113:9000/tron/'

  GetDrukujDokument(numer:string)
  {
    return this.http.get(this.baseAddress+'ogolne/getwydrukdokumentu?numer='+numer).map(result => result);
  }

Po stronie listy dokumentów

drukujDokument() {
    this.api.GetDrukujDokument(this.zaznaczoneDokumenty[0]).subscribe((result) => {
       console.log(result);
    });
  }

Wchodząc bezpośrednio w linki przez przeglądarkę działa bez problemów, zwraca mi elegancko mojego pdfa. Czyli problem leży po stronie klienta?

2
AdamWox napisał(a):

Wchodząc bezpośrednio w linki przez przeglądarkę działa bez problemów, zwraca mi elegancko mojego pdfa. Czyli problem leży po stronie klienta?

Yup, angularowy HttpClient w metodzie get oczekuje że webapi zwróci jsona, a zwracasz pdfa z web api.

zmień na :

GetDrukujDokument(numer:string)
  {
    return this.http.get(this.baseAddress+'ogolne/?numer='+numer, {      responseType: "blob"    }).map(result => result);
  }
0

Wybaczcie mi posty z takimi pierdołami. To są moje początki z Angularem i nie wszystko jeszcze ogarniam... Dzięki za pomoc, wszystko działa jak powinno.

1

Dlatego właśnie pytałem jak to pobierasz..

1 użytkowników online, w tym zalogowanych: 0, gości: 1