Попробовал в ответе отправить заголовок Content-Type: video/mp4
. Вместо открытия диалога, браузер пытается воспроизводить несуществующий файл, но пишет, что это невозможно. Но это фигня. Я не планирую подключаться к этому серверу из браузера.
Я сейчас не могу понять, как отправить файл клиенту.
В своём менеджере закачки, я писал вот такой код:
public int GetResponseStream(string url, long rangeFrom, long rangeTo, out Stream stream)
{
stream = null;
if (!FileDownloader.IsRangeValid(rangeFrom, rangeTo))
{
return FileDownloader.DOWNLOAD_ERROR_RANGE;
}
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
if (Headers != null)
{
SetRequestHeaders(request, Headers);
}
AddRange(request, rangeFrom, rangeTo);
webResponse = (HttpWebResponse)request.GetResponse();
int statusCode = (int)webResponse.StatusCode;
if (statusCode == 200 || statusCode == 206)
{
stream = webResponse.GetResponseStream();
}
return statusCode;
}
catch (WebException ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
LastErrorMessage = ex.Message;
if (webResponse != null)
{
webResponse.Dispose();
webResponse = null;
}
if (ex.Status == WebExceptionStatus.ProtocolError)
{
HttpWebResponse httpWebResponse = (HttpWebResponse)ex.Response;
int statusCode = (int)httpWebResponse.StatusCode;
return statusCode;
}
else
{
return ex.HResult;
}
}
catch (NotSupportedException ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
LastErrorMessage = ex.Message;
if (webResponse != null)
{
webResponse.Dispose();
webResponse = null;
}
return FileDownloader.DOWNLOAD_ERROR_INVALID_URL;
}
catch (UriFormatException ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
LastErrorMessage = ex.Message;
if (webResponse != null)
{
webResponse.Dispose();
webResponse = null;
}
return FileDownloader.DOWNLOAD_ERROR_INVALID_URL;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
LastErrorMessage = ex.Message;
if (webResponse != null)
{
webResponse.Dispose();
webResponse = null;
}
return ex.HResult;
}
}
private int ContentToStream(WebContent content, Stream stream)
{
if (content == null || content.ContentData == null)
{
return DOWNLOAD_ERROR_NULL_CONTENT;
}
try
{
byte[] buf = new byte[4096];
int iter = 0;
do
{
int bytesRead = content.ContentData.Read(buf, 0, buf.Length);
if (bytesRead <= 0)
{
break;
}
stream.Write(buf, 0, bytesRead);
_bytesTransfered += bytesRead;
StreamSize = stream.Length;
if (WorkProgress != null && (ProgressUpdateInterval == 0 || iter++ >= ProgressUpdateInterval))
{
WorkProgress.Invoke(this, _bytesTransfered, content.Length);
iter = 0;
}
if (CancelTest != null)
{
bool stop = false;
CancelTest.Invoke(this, ref stop);
Stopped = stop;
if (Stopped)
{
break;
}
}
}
while (true);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
LastErrorMessage = ex.Message;
return ex.HResult;
}
if (Stopped)
{
return DOWNLOAD_ERROR_CANCELED_BY_USER;
}
else if (content.Length >= 0L && _bytesTransfered != content.Length)
{
return DOWNLOAD_ERROR_INCOMPLETE_DATA_READ;
}
return 200;
}
Надо будет попробовать подключиться этим кодом к серверу и в дебаггере посмотреть, какие запросы приходят. Может тогда станет понятнее.
Самое главное - вот эта часть:
do
{
int bytesRead = content.ContentData.Read(buf, 0, buf.Length);
if (bytesRead <= 0)
{
break;
}
stream.Write(buf, 0, bytesRead);
_bytesTransfered += bytesRead;
...........
Я не пойму, что должно происходить на сервере в этот момент
Предположу, что при выполнении этих строчек клиентом
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
if (Headers != null)
{
SetRequestHeaders(request, Headers);
}
AddRange(request, rangeFrom, rangeTo);
webResponse = (HttpWebResponse)request.GetResponse();
int statusCode = (int)webResponse.StatusCode;
if (statusCode == 200 || statusCode == 206)
{
stream = webResponse.GetResponseStream();
}
сервер должен открыть файл на чтение (кажется режим называется что-то типа shared read
) и держать его открытым (в отдельном потоке, разумеется), пока клиент выполняет цикл скачивания
do
{
int bytesRead = content.ContentData.Read(buf, 0, buf.Length);
if (bytesRead <= 0)
{
break;
}
stream.Write(buf, 0, bytesRead);
_bytesTransfered += bytesRead;
...........
При этом, сервер автоматически будет отдавать клиенту нужные байты файла. А когда клиент отвалился - закрываем файл на сервере.
Правильно?