Qual è il design più sensato per rendere i file disponibili per il download da un URL?

3

Questo è quello che devo fare, in poche parole:

  1. Genera file di fogli di calcolo Excel (programmaticamente).

  2. Archivia questi file .xlsx in un percorso a cui possono accedere gli utenti successivamente. Questi file devono essere "su Internet / nel cloud", poiché la maggior parte dei downloader legittimi non sono utenti interni e quindi non si trovano nella rete della nostra azienda)

  3. Rendi questi file disponibili all'utente in modo che possano scaricarli tramite un collegamento su una pagina Web.

Questo è quello che ho fatto finora:

Il passaggio 1, la generazione programmatica dei file .xlsx, è completo. Attualmente, tuttavia, questi vengono salvati in una cartella locale sulla macchina su cui viene eseguita l'app (un'app di Winforms che consente all'utente di selezionare i criteri necessari per generare i report utilizzando i dati corretti).

Come per i passaggi 2 e 3, ho creato un progetto Web API (C #, ASP.NET) che presenta una pagina basata sulla logica di routing (il tipo di report, la società per la quale è stato generato il report, come parametri per le date del rapporto convers). Sto visualizzando la pagina appropriata, ma il link di download che sto generando tramite HTML non funziona. A quanto pare, il problema è che la posizione nel progetto web (la cartella App_Data) in cui sto salvando i file .xlsx generati non è accessibile o non viene rappresentata correttamente.

Ho provato "tutto" per far funzionare il collegamento per il download, come si può vedere qui, su StackOverflow , ma mi chiedo se devo fare un passo indietro per considerare di provare qualcosa di fondamentalmente diverso , dato che mi sento come se stessi sbattendo la testa contro il muro con questo approccio.

A partire da ora, sto solo testando file di fogli di calcolo molto semplici che l'app Web API genera dinamicamente (non quelli generati dall'app Winform). Potrei:

  • Utilizza lo stesso codice nell'app Web API che sto utilizzando nell'app Winforms per generare questi file .xlsx.
  • Invia i file .xlsx dall'app Winforms all'app dell'API Web, ma non so come farlo. Dove posso inviarli? Sicuramente non direttamente nella cartella App_Data dell'app Web API, ma come / dove?

Il modo in cui i metodi REST funzionano ora è che ho un metodo GET per l'URL REST che cerca il file generato corrispondente; se esiste già (il file è stato precedentemente generato), lo rende in una pagina. Se il file non esiste ancora, il metodo GET chiama il metodo POST, che genera il file; quindi, il file esiste e il file appena generato viene visualizzato su una nuova pagina:

[RoutePrefix("api/fillrate")]
public class FillRateController : ApiController
{
    [Route("{unit}/{begindate}")]
    // URL would be something like "http://localhost:52194/api/fillrate/Gramps/201509"
    public HttpResponseMessage Get(string unit, string begindate)
    {
        string _unit = unit;
        string _begindate = begindate; 
        string appDataFolder = 
HttpContext.Current.Server.MapPath("~/App_Data/");

        string fillRatefillRateByDistByCustFilename = 
string.Format("fillRateByDistByCust_{0}_{1}.html", _unit, _begindate);
        string fillRateFullPath = Path.Combine(appDataFolder, 
fillRatefillRateByDistByCustFilename);

        // If report has been generated, open it from its file (in AppData 
folder); 
        // otherwise, generate it now; in this way, any date range for this 
report can be requested
        if (!File.Exists(fillRateFullPath))
        {
            Post(unit, begindate);
        }
        var HtmlToDisplay = File.ReadAllText(fillRateFullPath);

        return new HttpResponseMessage()
        {
            Content = new StringContent(
                HtmlToDisplay,
                Encoding.UTF8,
                "text/html"
            )
        };
    }

    [Route("{unit}/{begindate}")]
    [HttpPost]
    public void Post(string unit, string begindate)
    {
        string _unit = unit;
        string _begindate = String.Format("{0}01", 
HyphenizeYYYYMM(begindate));
        string _enddate = GetEndOfMonthFor(_begindate);
        string appDataFolder = 
HttpContext.Current.Server.MapPath("~/App_Data/");
        DataTable dtFillRateResults = null;
        List<FillRateByDistributorByCustomer> 
_fillRateByDistributorByCustomerList = null;
        List<FillRateByDCByLocation> _fillRateByDCByLocationList = null;
        List<string> _members = SQLDBHelper.GetMemberStringList();
        try
        {
            foreach (String _memberId in _members)
            {
                dtFillRateResults =
                    SQLDBHelper.ExecuteSQLReturnDataTable(
                    . . .
                );
            . . .
            // Create minimalistic spreadsheet file for now
            var fillRateByDistByCustHtmlStr =
              ConvertFillRateByDistributorByCustomer(_fillRateByDistributorByCustomerList, 
unit, begindate);
            string fillRatefillRateByDistByCustFilename = 
string.Format("fillRateByDistByCust_{0}_{1}.html", _unit, begindate);
            string fullFillRateByDistByCustPath = 
Path.Combine(appDataFolder, fillRatefillRateByDistByCustFilename);
            File.WriteAllText(fullFillRateByDistByCustPath, 
fillRateByDistByCustHtmlStr);
        }
        catch (Exception ex)
        {
            . . .
        }
    }

Queste pagine renderizzate hanno un link per il download da cui è possibile scaricare il file .xlsx (se solo funziona, piuttosto che fingere l'ignoranza della cartella App_Data).

Quindi questo è un design / approccio sensato, o qualcos'altro è indicato? Sicuramente questo non è un requisito unico che non è mai stato risolto prima, quindi qual è il "metodo preferito" o l'approccio canonico per farlo?

UPDATE

Quello che ho intenzione di fare, e sono nel mezzo dell'attuazione, è questo:

1) Memorizza i file in un database (dall'app Winforms)

2) Nell'app API Web ASP.NET, generare un set di collegamenti su una pagina, uno per ciascun report salvato

3) Questi collegamenti avranno ciascuno un href ancora un altro indirizzo REST, che risponderà leggendo il file dal database e scaricandolo

    
posta B. Clay Shannon 30.03.2016 - 17:33
fonte

1 risposta

2

Mentre è semplice caricare i file su un server web e permetterne l'accesso è un'opzione.

Ci sono un paio di potenziali requisiti da prendere in considerazione.

1: autenticazione dell'utente che richiede il file.

2: accesso ai file per campi diversi dal nome file.

Questo tipo di cose può guidarti verso l'approccio che sembri prendere. Vale a dire

1: I file sono memorizzati su un database o altro repository di file privato.

2: viene esposto un Api che gestisce una richiesta in entrata, individua il file, lo legge dall'archivio e restituisce i dati.

Avere l'API di fronte all'accesso ai file ti offre un posto comodo per aggiungere autenticazione, registrazione, restituzione di elenchi di file, ecc.

Quando decidi quale tipo di repository utilizzare per archiviare il file, dovresti considerare che probabilmente vorresti anche memorizzare alcuni metadati insieme al file; per cui un db è una buona opzione.

La memorizzazione del file stesso in un db può essere considerata controversa. Tuttavia, credo che mssql offra almeno alcune buone opzioni qui.

Potresti anche prendere in considerazione varie opzioni di archiviazione basate su cloud. Ad esempio Amazon S3.

Avere un'API in primo piano significa che puoi astrarre il metodo di archiviazione dal metodo di accesso.

Anche nel tuo caso specifico l'API potrebbe generare il file e salvarlo se non è stato precedentemente creato. Rimozione della necessità dell'app di moduli di vincita

    
risposta data 02.04.2016 - 11:04
fonte

Leggi altre domande sui tag