I have an Active wave recording wave-file.wav happening to the Source folder.
I need to replicate this file to Destination folder with a new name wave-file-copy.wav.
The recording and replication should happen in parallel.
I have implemented a scheduled job, which will run in every 10 minutes and copy the source file to destination.
private static void CopyWaveFile(string destinationFile, string sourceFile){
using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
using (var reader = new WaveFileReader(fs)){
using (var writer = new WaveFileWriter(destinationFile, reader.WaveFormat)){
reader.Position = 0;
var endPos = (int)reader.Length;
var buffer = new byte[1024];
while (reader.Position < endPos){
var bytesRequired = (int)(endPos - reader.Position);
if (bytesRequired <= 0) continue;
var bytesToRead = Math.Min(bytesRequired, buffer.Length);
var bytesRead = reader.Read(buffer, 0, bytesToRead);
if (bytesRead > 0){
writer.Write(buffer, 0, bytesRead);
}
}
}
}
}
}
The copy operation is working fine, even though the source file is being updated continuously.
Time taken for the copy operation is increasing in linear time, because i am copying the entire file every time.
I am trying to implement a new function ConcatenateWavFiles(), which should update the content of destination file, with the latest available bytes of source recording.
I have tried few sample codes - the approach i am using is :
Read destination file meta info, and get the length.
Set the length of destination file as reader.Position of source file waveReader
Read the source file till end, starting from position.
public static void ConcatenateWavFiles(string destinationFile, string sourceFile){
WaveFileWriter waveFileWriter = null;
var sourceReadOffset = GetWaveFileSize(destinationFile);
try{
using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var reader = new WaveFileReader(fs))
{
waveFileWriter = new WaveFileWriter(destinationFile, reader.WaveFormat);
if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat)){
throw new InvalidOperationException(
"Can't append WAV Files that don't share the same format");
}
var startPos = sourceReadOffset - sourceReadOffset % reader.WaveFormat.BlockAlign;
var endPos = (int) reader.Length;
reader.Position = startPos;
var bytesRequired = (int)(endPos - reader.Position);
var buffer = new byte[bytesRequired];
if (bytesRequired > 0)
{
var bytesToRead = Math.Min(bytesRequired, buffer.Length);
var bytesRead = reader.Read(buffer, 0, bytesToRead);
if (bytesRead > 0)
{
waveFileWriter.Write(buffer, startPos, bytesRead);
}
}
}
}
}
finally{
if (waveFileWriter != null){
waveFileWriter.Dispose();
}
}
}
I was able to get the new content.
Is it possible to append the latest content to existing destination file?
If possible what am I doing wrong in the code?
My code throws the following exception - Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
I couldn't find a solution to wave audio file replication with NAudio Library.
But I have implemented a solution using C# MemoryStreams and FileStreams.
Copy the Source file to destination, if destination file doesn't exist.
Append all the latest bytes (recorded after the last operation) to the destination file.
Modify the Wave File Header to to reflect the last appended bytes. (Else the duration of the file will not be updated, only the file size will increase.
Repeat this append operation in regular intervals.
public void ReplicateFile(string destinationFile, string sourceFile){
if (!Directory.Exists(GetRoutePathFromFile(sourceFile)))
return;
if (!File.Exists(sourceFile))
return;
if (Directory.Exists(GetRoutePathFromFile(destinationFile))){
if (File.Exists(destinationFile)){
UpdateLatestWaveFileContent(destinationFile, sourceFile);
}else{
CopyWaveFile(destinationFile, sourceFile);
}
}else{
Directory.CreateDirectory(GetRoutePathFromFile(destinationFile));
CopyWaveFile(destinationFile, sourceFile);
}
}
private static string GetRoutePathFromFile(string file){
var rootPath = Directory.GetParent(file);
return rootPath.FullName;
}
private static void CopyWaveFile(string destination, string source){
var sourceMemoryStream = new MemoryStream();
using (var fs = File.Open(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
fs.CopyTo(sourceMemoryStream);
}
using (var fs = new FileStream(destination, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite)){
sourceMemoryStream.WriteTo(fs);
}
}
private static void UpdateLatestWaveFileContent(string destinationFile, string sourceFile){
var sourceMemoryStream = new MemoryStream();
long offset = 0;
using (var fs = File.Open(destinationFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
offset = fs.Length;
}
using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
fs.CopyTo(sourceMemoryStream);
}
var length = sourceMemoryStream.Length - offset;
var buffer = sourceMemoryStream.GetBuffer();
using (var fs = new FileStream(destinationFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)){
fs.Write(buffer, (int)offset, (int)length);
}
var bytes = new byte[45];
for (var i = 0; i < 45; i++){
bytes[i] = buffer[i];
}
ModifyHeaderDataLength(destinationFile, 0, bytes);
}
private static void ModifyHeaderDataLength(string filename, int position, byte[] data){
using (Stream stream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
{
stream.Position = position;
stream.Write(data, 0, data.Length);
}
}
Try Reading the Source File one or two Wav blocks prior to the actual end of the source file.
The case could be that the code is judging the end of the source file too close for comfort.
Related
I make an archiver with block-by-block reading and file compression. I put the compressed block in FileStream.
I am reading the 5 mb block. The problem is that if I compress a pic of 8 mb, then when I pull it out of the resulting archive, its sum-hash does not match the original and it opens pic halfway, and the size is the same... I don’t know what to try. I ask for help.
Read chunk void:
private byte[] ReadChunk(int chunkId)
{
using (var inFile = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read))
{
long filePosition = chunkId * chunkDataSize;
int bytesRead;
if (inFile.Length - filePosition <= chunkDataSize)
{
bytesRead = (int)(inFile.Length - filePosition);
}
else
{
bytesRead = chunkDataSize;
}
var lastBuffer = new byte[bytesRead];
inFile.Read(lastBuffer, 0, bytesRead);
return lastBuffer;
}
}
Compress and write void:
private void CompressBlock(byte[] bytesTo)
{
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gs = new GZipStream(ms, CompressionMode.Compress))
{
gs.Write(bytesTo, 0, bytesTo.Length);
}
byte[] compressedData = ms.ToArray();
using (var outFile = new FileStream(resultFile, FileMode.Append))
{
BitConverter.GetBytes(compressedData.Length).CopyTo(compressedData, 4);
outFile.Write(compressedData, 0, compressedData.Length);
}
}
}
I am trying to upload a large file (1 GB) from code to SharePoint 2013 on prem. I followed this tutorial, I dowloaded from NuGet the package "Microsoft.SharePointOnline.CSOM" and tried this piece of code:
public Microsoft.SharePoint.Client.File UploadFileSlicePerSlice(ClientContext ctx, string libraryName, string fileName, int fileChunkSizeInMB = 3)
{
// Each sliced upload requires a unique ID.
Guid uploadId = Guid.NewGuid();
// Get the name of the file.
string uniqueFileName = Path.GetFileName(fileName);
// Ensure that target library exists, and create it if it is missing.
if (!LibraryExists(ctx, ctx.Web, libraryName))
{
CreateLibrary(ctx, ctx.Web, libraryName);
}
// Get the folder to upload into.
List docs = ctx.Web.Lists.GetByTitle(libraryName);
ctx.Load(docs, l => l.RootFolder);
// Get the information about the folder that will hold the file.
ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
ctx.ExecuteQuery();
// File object.
Microsoft.SharePoint.Client.File uploadFile;
// Calculate block size in bytes.
int blockSize = fileChunkSizeInMB * 1024 * 1024;
// Get the information about the folder that will hold the file.
ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
ctx.ExecuteQuery();
// Get the size of the file.
long fileSize = new FileInfo(fileName).Length;
if (fileSize <= blockSize)
{
// Use regular approach.
using (FileStream fs = new FileStream(fileName, FileMode.Open))
{
FileCreationInformation fileInfo = new FileCreationInformation();
fileInfo.ContentStream = fs;
fileInfo.Url = uniqueFileName;
fileInfo.Overwrite = true;
uploadFile = docs.RootFolder.Files.Add(fileInfo);
ctx.Load(uploadFile);
ctx.ExecuteQuery();
// Return the file object for the uploaded file.
return uploadFile;
}
}
else
{
// Use large file upload approach.
ClientResult<long> bytesUploaded = null;
FileStream fs = null;
try
{
fs = System.IO.File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (BinaryReader br = new BinaryReader(fs))
{
byte[] buffer = new byte[blockSize];
Byte[] lastBuffer = null;
long fileoffset = 0;
long totalBytesRead = 0;
int bytesRead;
bool first = true;
bool last = false;
// Read data from file system in blocks.
while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
{
totalBytesRead = totalBytesRead + bytesRead;
// You've reached the end of the file.
if (totalBytesRead == fileSize)
{
last = true;
// Copy to a new buffer that has the correct size.
lastBuffer = new byte[bytesRead];
Array.Copy(buffer, 0, lastBuffer, 0, bytesRead);
}
if (first)
{
using (MemoryStream contentStream = new MemoryStream())
{
// Add an empty file.
FileCreationInformation fileInfo = new FileCreationInformation();
fileInfo.ContentStream = contentStream;
fileInfo.Url = uniqueFileName;
fileInfo.Overwrite = true;
uploadFile = docs.RootFolder.Files.Add(fileInfo);
// Start upload by uploading the first slice.
using (MemoryStream s = new MemoryStream(buffer))
{
// Call the start upload method on the first slice.
bytesUploaded = uploadFile.StartUpload(uploadId, s);
ctx.ExecuteQuery();//<------here exception
// fileoffset is the pointer where the next slice will be added.
fileoffset = bytesUploaded.Value;
}
// You can only start the upload once.
first = false;
}
}
else
{
// Get a reference to your file.
uploadFile = ctx.Web.GetFileByServerRelativeUrl(docs.RootFolder.ServerRelativeUrl + System.IO.Path.AltDirectorySeparatorChar + uniqueFileName);
if (last)
{
// Is this the last slice of data?
using (MemoryStream s = new MemoryStream(lastBuffer))
{
// End sliced upload by calling FinishUpload.
uploadFile = uploadFile.FinishUpload(uploadId, fileoffset, s);
ctx.ExecuteQuery();
// Return the file object for the uploaded file.
return uploadFile;
}
}
else
{
using (MemoryStream s = new MemoryStream(buffer))
{
// Continue sliced upload.
bytesUploaded = uploadFile.ContinueUpload(uploadId, fileoffset, s);
ctx.ExecuteQuery();
// Update fileoffset for the next slice.
fileoffset = bytesUploaded.Value;
}
}
}
} // while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
}
}
finally
{
if (fs != null)
{
fs.Dispose();
}
}
}
return null;
}
But I'm getting runtime exception : ServerExecution with the message: Method "StartUpload" does not exist at line "ctx.ExecuteQuery();" (<-- I marked this line in the code)
I also tried with SharePoint2013 package and the method "startupload" doesn't supported in this package.
UPDATE:
Adam's code worked for ~1GB files it turns out that inside web.config in the path : C:\inetpub\wwwroot\wss\VirtualDirectories\{myport}\web.config
at the part <requestLimit maxAllowedContentLength="2000000000"/> that's in bytes and not kilobytes as I thougt at the begining, therefore I changed to 2000000000 and it worked.
method to upload 1 GB file on SP 2013 using CSOM that works (tested and developed for couple of days of trying different approaches :) )
try
{
Console.WriteLine("start " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
using (ClientContext context = new ClientContext("[URL]"))
{
context.Credentials = new NetworkCredential("[LOGIN]","[PASSWORD]","[DOMAIN]");
context.RequestTimeout = -1;
Web web = context.Web;
if (context.HasPendingRequest)
context.ExecuteQuery();
byte[] fileBytes;
using (var fs = new FileStream(#"D:\OneGB.rar", FileMode.Open, FileAccess.Read))
{
fileBytes = new byte[fs.Length];
int bytesRead = fs.Read(fileBytes, 0, fileBytes.Length);
}
using (var fileStream = new System.IO.MemoryStream(fileBytes))
{
Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, "/Shared Documents/" + "OneGB.rar", fileStream, true);
}
}
Console.WriteLine("end " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
}
catch (Exception ex)
{
Console.WriteLine("error -> " + ex.Message);
}
finally
{
Console.ReadLine();
}
Besides this I had to:
extend the max file upload on CA for this web application,
set on CA for this web application 'web page security Validation' on
Never (in this link there is a screen how to set it)
extend timeout on IIS
and the final result is:
sorry for the lang but I usually work in PL
all history defined here post
Install the SharePoint Online CSOM library using the command below.
Install-Package Microsoft.SharePointOnline.CSOM -Version 16.1.8924.1200
Then use the code below to upload the large file.
int blockSize = 8000000; // 8 MB
string fileName = "C:\\temp\\6GBTest.odt", uniqueFileName = String.Empty;
long fileSize;
Microsoft.SharePoint.Client.File uploadFile = null;
Guid uploadId = Guid.NewGuid();
using (ClientContext ctx = new ClientContext("siteUrl"))
{
ctx.Credentials = new SharePointOnlineCredentials("user#tenant.onmicrosoft.com", GetSecurePassword());
List docs = ctx.Web.Lists.GetByTitle("Documents");
ctx.Load(docs.RootFolder, p => p.ServerRelativeUrl);
// Use large file upload approach
ClientResult<long> bytesUploaded = null;
FileStream fs = null;
try
{
fs = System.IO.File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
fileSize = fs.Length;
uniqueFileName = System.IO.Path.GetFileName(fs.Name);
using (BinaryReader br = new BinaryReader(fs))
{
byte[] buffer = new byte[blockSize];
byte[] lastBuffer = null;
long fileoffset = 0;
long totalBytesRead = 0;
int bytesRead;
bool first = true;
bool last = false;
// Read data from filesystem in blocks
while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
{
totalBytesRead = totalBytesRead + bytesRead;
// We've reached the end of the file
if (totalBytesRead <= fileSize)
{
last = true;
// Copy to a new buffer that has the correct size
lastBuffer = new byte[bytesRead];
Array.Copy(buffer, 0, lastBuffer, 0, bytesRead);
}
if (first)
{
using (MemoryStream contentStream = new MemoryStream())
{
// Add an empty file.
FileCreationInformation fileInfo = new FileCreationInformation();
fileInfo.ContentStream = contentStream;
fileInfo.Url = uniqueFileName;
fileInfo.Overwrite = true;
uploadFile = docs.RootFolder.Files.Add(fileInfo);
// Start upload by uploading the first slice.
using (MemoryStream s = new MemoryStream(buffer))
{
// Call the start upload method on the first slice
bytesUploaded = uploadFile.StartUpload(uploadId, s);
ctx.ExecuteQuery();
// fileoffset is the pointer where the next slice will be added
fileoffset = bytesUploaded.Value;
}
// we can only start the upload once
first = false;
}
}
else
{
// Get a reference to our file
uploadFile = ctx.Web.GetFileByServerRelativeUrl(docs.RootFolder.ServerRelativeUrl + System.IO.Path.AltDirectorySeparatorChar + uniqueFileName);
if (last)
{
// Is this the last slice of data?
using (MemoryStream s = new MemoryStream(lastBuffer))
{
// End sliced upload by calling FinishUpload
uploadFile = uploadFile.FinishUpload(uploadId, fileoffset, s);
ctx.ExecuteQuery();
// return the file object for the uploaded file
return uploadFile;
}
}
else
{
using (MemoryStream s = new MemoryStream(buffer))
{
// Continue sliced upload
bytesUploaded = uploadFile.ContinueUpload(uploadId, fileoffset, s);
ctx.ExecuteQuery();
// update fileoffset for the next slice
fileoffset = bytesUploaded.Value;
}
}
}
}
}
}
finally
{
if (fs != null)
{
fs.Dispose();
}
}
}
Or download the example code from GitHub.
Large file upload with CSOM
I'm looking for a way to upload 1GB file to SharePoint 2013
You can change the upload limit with the PowerShell below:
$a = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$a.ClientRequestServiceSettings.MaxReceivedMessageSize = 209715200
$a.Update()
References:
https://thuansoldier.net/4328/
https://blogs.msdn.microsoft.com/sridhara/2010/03/12/uploading-files-using-client-object-model-in-sharepoint-2010/
https://social.msdn.microsoft.com/Forums/en-US/09a41ba4-feda-4cf3-aa29-704cd92b9320/csom-microsoftsharepointclientserverexception-method-8220startupload8221-does-not-exist?forum=sharepointdevelopment
Update:
SharePoint CSOM request size is very limited, it cannot exceed a 2 MB limit and you cannot change this setting in Office 365 environment. If you have to upload bigger files you have to use REST API. Here is MSDN reference https://msdn.microsoft.com/en-us/library/office/dn292553.aspx
Also see:
https://gist.github.com/vgrem/10713514
File Upload to SharePoint 2013 using REST API
Ref: https://sharepoint.stackexchange.com/posts/149105/edit (see the 2nd answer).
Elmah has recently reported this bug;
Microsoft.SharePoint.Client.ServerException: The request message is too big. The server does not allow messages larger than 5242880 bytes.
The code where it fell over was;
public SharepointFileInfo Save(byte[] file, string fileName)
{
using (var context = new ClientContext(this.SharepointServer))
{
context.Credentials = new NetworkCredential(this.UserName, this.Password, this.Domain);
var list = context.Web.Lists.GetByTitle(this.DocumentLibrary);
var fileCreationInformation = new FileCreationInformation
{
Content = file,
Overwrite = true,
Url = fileName
};
var uploadFile = list.RootFolder.Files.Add(fileCreationInformation);
var listItem = uploadFile.ListItemAllFields;
listItem.Update();
context.ExecuteQuery();
if (this.Metadata.Count > 0)
{
this.SaveMetadata(uploadFile, context);
}
return GetSharepointFileInfo(context, list, uploadFile);
}
}
I am using Sharepoint 2013.
How do I fix this?
It's a normal problme. You use the classic API (new FileCreationInformation [...] context.ExecuteQuery()) which sent a HTTP requet to the server. You file is up to 5 Mb. So, IIS receive a huge request, and reject it.
To Upload a file to SharePoint you need to use :
File.SaveBinaryDirect
(with this you don't need to change settings ;) )
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
Microsoft.SharePoint.Client.File.SaveBinaryDirect(ctx, string.Format("/{0}/{1}", libraryName, System.IO.Path.GetFileName(filePath)), fs, true);
}
Check this links to see how to upload a file to SharePoint using CSOM :
Upload large files sample app for SharePoint
good luck
There is several approche to do that (upload file with metaData). I propose 2 methods to you (one simple, second more complex)
In 2 Times (simple)
Upload the the file with the File.SaveBinaryDirect
Get the SPFile with CSOM by the file URL with SP.Web.getFileByServerRelativeUrl and File.listItemAllFields methodes.
Here an exemple : get listitem by file URL
With FileCreationInformation but more complex.
You need to use : File.StartUpload, File.ContinueUpload and File.FinishUpload
The code is from Microsoft the last part of the tuto, not mine
public Microsoft.SharePoint.Client.File UploadFileSlicePerSlice(ClientContext ctx, string libraryName, string fileName,int fileChunkSizeInMB = 3){
// Each sliced upload requires a unique ID.
Guid uploadId = Guid.NewGuid();
// Get the name of the file.
string uniqueFileName = Path.GetFileName(fileName);
// Ensure that target library exists, and create it if it is missing.
if (!LibraryExists(ctx, ctx.Web, libraryName))
{
CreateLibrary(ctx, ctx.Web, libraryName);
}
// Get the folder to upload into.
List docs = ctx.Web.Lists.GetByTitle(libraryName);
ctx.Load(docs, l => l.RootFolder);
// Get the information about the folder that will hold the file.
ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
ctx.ExecuteQuery();
// File object.
Microsoft.SharePoint.Client.File uploadFile;
// Calculate block size in bytes.
int blockSize = fileChunkSizeInMB * 1024 * 1024;
// Get the information about the folder that will hold the file.
ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
ctx.ExecuteQuery();
// Get the size of the file.
long fileSize = new FileInfo(fileName).Length;
if (fileSize <= blockSize)
{
// Use regular approach.
using (FileStream fs = new FileStream(fileName, FileMode.Open))
{
FileCreationInformation fileInfo = new FileCreationInformation();
fileInfo.ContentStream = fs;
fileInfo.Url = uniqueFileName;
fileInfo.Overwrite = true;
uploadFile = docs.RootFolder.Files.Add(fileInfo);
ctx.Load(uploadFile);
ctx.ExecuteQuery();
// Return the file object for the uploaded file.
return uploadFile;
}
}
else
{
// Use large file upload approach.
ClientResult<long> bytesUploaded = null;
FileStream fs = null;
try
{
fs = System.IO.File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (BinaryReader br = new BinaryReader(fs))
{
byte[] buffer = new byte[blockSize];
Byte[] lastBuffer = null;
long fileoffset = 0;
long totalBytesRead = 0;
int bytesRead;
bool first = true;
bool last = false;
// Read data from file system in blocks.
while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
{
totalBytesRead = totalBytesRead + bytesRead;
// You've reached the end of the file.
if (totalBytesRead == fileSize)
{
last = true;
// Copy to a new buffer that has the correct size.
lastBuffer = new byte[bytesRead];
Array.Copy(buffer, 0, lastBuffer, 0, bytesRead);
}
if (first)
{
using (MemoryStream contentStream = new MemoryStream())
{
// Add an empty file.
FileCreationInformation fileInfo = new FileCreationInformation();
fileInfo.ContentStream = contentStream;
fileInfo.Url = uniqueFileName;
fileInfo.Overwrite = true;
uploadFile = docs.RootFolder.Files.Add(fileInfo);
// Start upload by uploading the first slice.
using (MemoryStream s = new MemoryStream(buffer))
{
// Call the start upload method on the first slice.
bytesUploaded = uploadFile.StartUpload(uploadId, s);
ctx.ExecuteQuery();
// fileoffset is the pointer where the next slice will be added.
fileoffset = bytesUploaded.Value;
}
// You can only start the upload once.
first = false;
}
}
else
{
// Get a reference to your file.
uploadFile = ctx.Web.GetFileByServerRelativeUrl(docs.RootFolder.ServerRelativeUrl + System.IO.Path.AltDirectorySeparatorChar + uniqueFileName);
if (last)
{
// Is this the last slice of data?
using (MemoryStream s = new MemoryStream(lastBuffer))
{
// End sliced upload by calling FinishUpload.
uploadFile = uploadFile.FinishUpload(uploadId, fileoffset, s);
ctx.ExecuteQuery();
// Return the file object for the uploaded file.
return uploadFile;
}
}
else
{
using (MemoryStream s = new MemoryStream(buffer))
{
// Continue sliced upload.
bytesUploaded = uploadFile.ContinueUpload(uploadId, fileoffset, s);
ctx.ExecuteQuery();
// Update fileoffset for the next slice.
fileoffset = bytesUploaded.Value;
}
}
}
} // while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
}
}
finally
{
if (fs != null)
{
fs.Dispose();
}
}
}
return null;}
hope this help you
I have an active audio recording happening in WAV format with NAudio Library.
private void RecordStart() {
try {
_sourceStream = new WaveIn {
DeviceNumber = _recordingInstance.InputDeviceIndex,
WaveFormat =
new WaveFormat(
44100,
WaveIn.GetCapabilities(_recordingInstance.InputDeviceIndex).Channels)
};
_sourceStream.DataAvailable += SourceStreamDataAvailable;
if (!Directory.Exists(_recordingInstance.AudioFilePath)) {
Directory.CreateDirectory(_recordingInstance.AudioFilePath);
}
WaveFileWriter _waveWriter = new WaveFileWriter(
_recordingInstance.AudioFilePath + _recordingInstance.AudioFileName,
_sourceStream.WaveFormat);
_sourceStream.StartRecording();
}
catch (Exception exception) {
Log.Error("Recording failes", exception);
}
}
private void SourceStreamDataAvailable(object sender, WaveInEventArgs e) {
if (_waveWriter == null) return;
_waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
_waveWriter.Flush();
}
I want to copy the latest available content to another location. The copied file should be in WAV format, and should be able to play the available duration. Update the destination file, whenever more content is available.
I have Tried the following sample code (using NAudio) with a static WAV file, but the solution is not working.
The resulting WAV file created is corrupted - not in the correct format.
using (WaveFileReader reader = new WaveFileReader(remoteWavFile))
{
byte[] buffer = new byte[reader.Length];
int read = reader.Read(buffer, 0, buffer.Length);
}
When the recording is in progress, the code throws an exception "File is in use by another application".
I have solved the problem with help of NAudio Library itself.
When we only use the WaveFileReader class of NAudio. It will throw the exception - "file is in use by another application".
So I had to create a file stream, which opens the source file - live recording file, with File.Open(inPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) then pass this stream as an input of WaveFileReader.
Then create a WaveFileWritter class of NAudio, with the same WavFormat of the reader.
copied below is the code, i have used.
public static void CopyWavFile(string inPath, string outPath){
using (var fs = File.Open(inPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
using (var reader = new WaveFileReader(fs)){
using (var writer = new WaveFileWriter(outPath, reader.WaveFormat)){
reader.Position = 0;
var endPos = (int)reader.Length;
var buffer = new byte[1024];
while (reader.Position < endPos){
var bytesRequired = (int)(endPos - reader.Position);
if (bytesRequired <= 0) continue;
var bytesToRead = Math.Min(bytesRequired, buffer.Length);
var bytesRead = reader.Read(buffer, 0, bytesToRead);
if (bytesRead > 0){
writer.Write(buffer, 0, bytesRead);
}
}
}
}
}
}
Can we merge two memory mapped files? if so the how? if not then why not?
So here are my first experiences with MemoryMappedFiles, give it a try:
String f1Path = #"C:\Temp\Test1.txt";
String f2Path = #"C:\Temp\Test2.txt";
byte[] buffer;
int offset;
int length;
using (FileStream f1ReadStream = new FileStream(f1Path, FileMode.Open, FileAccess.Read))
{
offset = (int)f1ReadStream.Length;
}
using (FileStream f2ReadStream = new FileStream(f2Path, FileMode.Open, FileAccess.Read))
{
length = (int)f2ReadStream.Length;
}
// read file2 and append all to file1
using (var mappedFile2 = MemoryMappedFile.CreateFromFile(f2Path, FileMode.Open, null, length))
{
using (var reader = mappedFile2.CreateViewStream(0, length, MemoryMappedFileAccess.Read))
{
// Read from MMF
buffer = new byte[length];
reader.Read(buffer, 0, length);
}
}
using (var mappedFile1 = MemoryMappedFile.CreateFromFile(f1Path,FileMode.Open, null, offset + length))
{
// Create writer to MMF
using (var writer = mappedFile1.CreateViewAccessor(offset, length, MemoryMappedFileAccess.Write))
{
// Write to MMF
writer.WriteArray<byte>(0, buffer, 0, length);
}
}