2016-03-30 7 views
2

У меня есть приложение MVC, в котором есть действие, которое служит файлу. У меня есть требование, чтобы, если пользователь инициировал загрузку, пользователь не может инициировать новую загрузку до окончания текущей.Определить существующий Загрузить в MVC C# для приложения

Просто попробуйте скачать только один файл за один раз. Однако я не хочу просто блокировать запрос пользователя, но хочу сообщить им, что они не могут загрузить новый, поскольку они загружают существующий.

Так что мой вопрос: как вы отслеживаете, когда загрузка была запущена и еще не закончена? Первоначально я переключился на динамическое ограничение IP-адресов в IIS, но проблема заключается в том, что конечный пользователь может сидеть за слоями на слоях прокси-серверов, которые не могут сделать его надежным. Есть ли способ сделать это с помощью кода?

Я также попытался использовать FileWebRequest/FileWebResponse, который создает текущий поток. Но когда приходит новый запрос, он вводит новое действие, и я не знаю, как проверить, продолжает ли предыдущий поток.

public async Task<ActionResult> Download() 
    { 
     Session["IsDownloading"] = true;    
     await ServeFiles(); 
     return View("Index"); 
    } 

public ActionResult CheckStatus() 
    { 
     var message = Session["IsDownloading"] ?? "Null"; 
     return Content(message.ToString()); 
    } 
private async Task ServeFiles() 
{ 
    try 
    { //Download async 
    } 
    finaly 
    { 
     Session["IsDownloading"] = false; 
    } 
} 

*********************** Обновление ******************* **

Я обновил образец кода. Загрузить можно вызывать любое количество времени для загрузки файла в c: \ temp, а затем при загрузке я пытался вызвать CheckStatus, но он не отвечает во время загрузки. Только после завершения загрузки.

Здесь я добавил проектное решение. https://github.com/janmchan/DownloadThrottling.git

*********************** Обновление 2016-04-04 **********

После немного поиска я узнал, что сессия (я использую SQLServer) сохраняется в конце запроса, так что даже если пользователь управляет двумя параллельными запросами, переменная сеанса не будет обновляться до конца запроса, создающего информация в сеансе не надежна. Итак, теперь я ищу способ вручную принудительно сохранить состояние сеанса сразу после обновления значения.

+0

Сессия не будет работать для вас, поскольку сеанс специфичен для браузера (т. Е. Он основан на cookie, и каждый браузер обрабатывает файлы cookie по-разному). Поэтому (как я упоминаю в другом месте) все, что вам нужно сделать, это открыть другой браузер, чтобы обойти любую безопасность сеанса. Однако, если вы хотите использовать сеанс, вам нужно только установить флаг сеанса, а затем перенаправить браузер в загружаемый файл, это обеспечит обновление переменной сеанса до начала загрузки. –

+0

Вы также хотели бы объединить это с уникальным идентификатором загрузки, который генерируется «на лету», чтобы обратиться к определенному файлу, а затем, когда начинается загрузка, вы помечаете его в базе данных, как загружено для этого идентификатора, и не позволяете ему снова использоваться. –

ответ

0

Окончательное решение, которое я в конечном итоге использую, похоже на ответ @ eugen, но вместо сеанса, используя кеш данных (MemoryCache), который немедленно вступает в силу и не ждет завершения запроса.Хотя это только в процессе, это прекрасно, так как я узнал, что, несмотря на то, что серверы приложений будут сбалансированы по нагрузке, как только будет установлен сеанс, гарантируется инфраструктурой клиента, что они будут использовать один и тот же набор серверов для остальных сессии.

Я согласен с комментарием Эрика Функенбуша, что пользователь может легко обойти это, и это решение предназначено только для этого конкретного требования.

0

Мне кажется, вам нужно 3 вещи: определить пользователя, проверить + блок, если у него уже есть загрузка.

Самый простой способ - установить Session ["isDownloading"] = true; и затем проверьте это. Установите его на false, когда он закончит загрузку.

От клиента, когда он хочет начать загрузку, вы можете использовать javascript для вызова действия CheckIsDownloading, и если ok, обратитесь в Службу, чтобы получить файл.

В случае необходимости повторите попытку и заблокируйте, если он загружается, чтобы избежать сценариев, где он взламывает js и выполняет запросы на загрузку.

Примечание: идентификационная часть пользователя трудно сделать, если он не вошел в систему, и вы хотите убедиться, что это только одна загрузка. Он может удалять файлы cookie в любое время (-> новый сеанс) и выполнять новую загрузку.

+0

Я попробовал это, но не могу заставить его работать правильно. Поэтому я добавил сеанс [«IsDownloading»] = true в начале действия «Подача» и после загрузки его обновлений в значение «false». Затем я создал еще одно действие CheckStatus, которое только что прочитало сеанс, однако оно кажется заблокированным и не отвечает до тех пор, пока загрузка не завершится – MichaelChan

+0

не уверен, что вы имеете в виду, заблокировав, вы отлаживали это, и он остается на линии, где вы читаете сессию? это было бы странно. возможно, вы можете обновить свой вопрос с реализацией как клиента, так и сервера, не нужно включать фактический код чтения файла – eugen

+0

Обновленный вопрос и код. Если вы попытаетесь загрузить (Download1/2) и нажмите на статус проверки, он не отвечает до завершения загрузки. – MichaelChan