Envoyer et recevoir des fichiers volumineux sur les cours d'eau dans ASP.NET l'Api Web C#
Je travaille sur un projet où j'ai besoin d'envoyer de gros fichiers audio via les flux à partir d'un client à un serveur. Je suis à l'aide de la ASP.NET Web Api pour communiquer entre le client et le serveur. Mon client a un "SendFile" méthode qui, je crois, fonctionne très bien, mais je ne sais pas comment faire pour que mon serveur de recevoir les données que je vous fais parvenir par l'intermédiaire d'un flux. Mon client code ressemble à ceci:
private const int MAX_CHUNK_SIZE = (1024 * 5000);
private HttpWebRequest webRequest = null;
private FileStream fileReader = null;
private Stream requestStream = null;
public bool SendAudio(string uri, string file)
{
byte[] fileData;
fileReader = new FileStream(file, FileMode.Open, FileAccess.Read);
webRequest = (HttpWebRequest)WebRequest.Create(uri);
webRequest.Method = "POST";
webRequest.ContentLength = fileReader.Length;
webRequest.Timeout = 600000;
webRequest.Credentials = CredentialCache.DefaultCredentials;
webRequest.AllowWriteStreamBuffering = false;
requestStream = webRequest.GetRequestStream();
long fileSize = fileReader.Length;
long remainingBytes = fileSize;
int numberOfBytesRead = 0, done = 0;
while (numberOfBytesRead < fileSize)
{
SetByteArray(out fileData, remainingBytes);
done = WriteFileToStream(fileData, requestStream);
numberOfBytesRead += done;
remainingBytes -= done;
}
fileReader.Close();
return true;
}
public int WriteFileToStream(byte[] fileData, Stream requestStream)
{
int done = fileReader.Read(fileData, 0, fileData.Length);
requestStream.Write(fileData, 0, fileData.Length);
return done;
}
private void SetByteArray(out byte[] fileData, long bytesLeft)
{
fileData = bytesLeft < MAX_CHUNK_SIZE ? new byte[bytesLeft] : new byte[MAX_CHUNK_SIZE];
}
Mon serveur ressemble à ceci:
[HttpPost]
[ActionName("AddAudio")]
public async Task<IHttpActionResult> AddAudio([FromUri]string name)
{
try
{
isReceivingFile = true;
byte[] receivedBytes = await Request.Content.ReadAsByteArrayAsync();
if (WriteAudio(receivedBytes, name) == true)
{
isReceivingFile = false;
return Ok();
}
else
{
isReceivingFile = false;
return BadRequest("ERROR: Audio could not be saved on server.");
}
}
catch (Exception ex)
{
isReceivingFile = false;
return BadRequest("ERROR: Audio could not be saved on server.");
}
}
public bool WriteAudio(byte[] receivedBytes, string fileName)
{
string file = Path.Combine(@"C:\Users\username\Desktop\UploadedFiles", fileName);
using (FileStream fs = File.Create(file))
{
fs.Write(receivedBytes, 0, receivedBytes.Length);
}
return true;
}
Le code du serveur dispose de l'original de code que j'ai écrit pour elle, avant de décider de l'essayer et de le faire fonctionner avec des cours d'eau. Le serveur de code fonctionne toujours si j'envoie un fichier de petite taille (moins de 30 MO), mais si j'envoie un gros fichier de mon serveur reçoit une "exception outofmemoryexception". Je ne peux pas comprendre comment faire le serveur de données par le biais d'un flux. Dans ma recherche de solutions, j'ai rencontré beaucoup d'exemples avec des sockets et TCPClient, mais ce n'est pas la façon dont nous voulons le faire sur ce projet. Quelqu'un peut-il aider, s'il vous plaît?
C'est ce que je suis en train de faire maintenant. J'ai un MAX_CHUNK_SIZE fixé à 5 MO, donc la "WriteFileToStream" méthode obtient seulement 5 MO de données à la fois.
avez-vous augmenté le
maxAllowedContentLength
dans votre site web.config?Oui, je n'ai que trop: <requestLimits maxAllowedContentLength="2147483647"/>
OriginalL'auteur Tobiuo | 2017-04-28
Vous devez vous connecter pour publier un commentaire.
Bien, c'est la lecture de la ensemble du flux de déchets dans la mémoire ici:
Ce que vous voulez faire est de copie le flux à partir d'un emplacement à un autre, sans chargement en mémoire à la fois. Quelque chose comme ceci devrait fonctionner:
Salut @Stephen Cleary , j'ai une question, Est-il travail depuis plus de 4 GO de fichiers?
Je n'ai pas essayé, mais je pense qu'il devrait fonctionner.
Salut @StephenCleary. Est-il une manière que je pourrais utiliser ce code pour cible .NET framework 4.0 ? Je ne suis pas en mesure de mettre à niveau à 4,5 sur le serveur de production.
Vous devriez écrire à un flux de sortie. E. g., PushStreamContent sur ASP.NET Classic ou un custom FileCallbackResult sur ASP.NET Core.
OriginalL'auteur Stephen Cleary