I used this code to resample file and save it but the file sounds like fast-forward recording:
using (MediaFoundationReader reader = new MediaFoundationReader(url))
{
using (ResamplerDmoStream resampledReader = new ResamplerDmoStream(reader, new WaveFormat(16000, 16, 1)))
{
using (WaveFileWriter waveWriter = new WaveFileWriter(#"c:\test.wav", resampledReader.WaveFormat))
{
resampledReader.CopyTo(waveWriter);
}
}
}
The WaveFileWriter must have the same WaveFormat as resampledReader. So pass in resampledReader.WaveFormat to the WaveFileWriter constructor.
I'm not sure what resampling means, but if you need to get the wav from a video, this works...
using (var video = new MediaFoundationReader(file))
{
file = TempWav;
WaveFileWriter.CreateWaveFile(file, video);
}
Related
I have a .NET Core API that I'd like to extend to save uploaded images asynchronously.
Using ImageSharp I should be able to check uploads and resize if predefined size limits are exceeded. However I can't get a simple async save working.
A simple (non-async) save to file works without problem:
My Controller extracts IFormFile from the upload and calls the following method without any problem
public static void Save(IFormFile image, string imagesFolder)
{
var fileName = Path.Combine(imagesFolder, image.FileName);
using (var stream = image.OpenReadStream())
using (var imgIS = Image.Load(stream, out IImageFormat format))
{
imgIS.Save(fileName);
}
}
ImageSharp is currently lacking async methods so a workaround is necessary.
The updated code below saves the uploaded file but the format is incorrect - when viewing the file I get the message "It appears we don't support this file format".
The format is extracted from the ImageSharp Load method. and used when saving to MemoryStream.
MemoryStream CopyToAsync method is used to save to FileStream to make the upload asynchronous.
public static async void Save(IFormFile image, string imagesFolder)
{
var fileName = Path.Combine(imagesFolder, image.FileName);
using (var stream = image.OpenReadStream())
using (var imgIS = Image.Load(stream, out IImageFormat format))
using (var memoryStream = new MemoryStream())
using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate))
{
imgIS.Save(memoryStream, format);
await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false);
fileStream.Flush();
memoryStream.Close();
fileStream.Close();
}
}
I can't work out whether the issue is with ImageSharp Save to MemoryStream, or the MemoryStream.CopyToAsync.
I'm currently getting 404 on SixLabors docs - hopefully not an indication that the project has folded.
How can I make the upload async and save to file in the correct format?
CopyToAsync copies a stream starting at its current position. You must change the current position of memoryStream back to start before copying:
// ...
memoryStream.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false);
// ...
I have an existing library that I can use to receive a docx file and return it. The software is .Net Core hosted in a Linux Docker container.
It's very limited in scope though and I need to perform some actions it can't do. As these are straightforward I thought I would use OpenXML, and for my proof of concept all I need to do is to read a docx as a memorystream, replace some text, turn it back into a memorystream and return it.
However the docx that gets returned is unreadable. I've commented out the text replacement below to eliminate that, and if I comment out the call to the method below then the docx can be read so I'm sure the issue is in this method.
Presumably I'm doing something fundamentally wrong here but after a few hours googling and playing around with the code I am not sure how to correct this; any ideas what I have wrong?
Thanks for the help
private MemoryStream SearchAndReplace(MemoryStream mem)
{
mem.Position = 0;
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
{
string docText = null;
StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream());
docText = sr.ReadToEnd();
//Regex regexText = new Regex("Hello world!");
//docText = regexText.Replace(docText, "Hi Everyone!");
MemoryStream newMem = new MemoryStream();
newMem.Position = 0;
StreamWriter sw = new StreamWriter(newMem);
sw.Write(docText);
return newMem;
}
}
If your real requirement is to search and replace text in a WordprocessingDocument, you should have a look at this answer.
The following unit test shows how you can make your approach work if the use case really demands that you read a string from a part, "massage" the string, and write the changed string back to the part. It also shows one of the shortcomings of any other approach than the one described in the answer already mentioned above, e.g., by demonstrating that the string "Hello world!" will not be found in this way if it is split across w:r elements.
[Fact]
public void CanSearchAndReplaceStringInOpenXmlPartAlthoughThisIsNotTheWayToSearchAndReplaceText()
{
// Arrange.
using var docxStream = new MemoryStream();
using (var wordDocument = WordprocessingDocument.Create(docxStream, WordprocessingDocumentType.Document))
{
MainDocumentPart part = wordDocument.AddMainDocumentPart();
var p1 = new Paragraph(
new Run(
new Text("Hello world!")));
var p2 = new Paragraph(
new Run(
new Text("Hello ") { Space = SpaceProcessingModeValues.Preserve }),
new Run(
new Text("world!")));
part.Document = new Document(new Body(p1, p2));
Assert.Equal("Hello world!", p1.InnerText);
Assert.Equal("Hello world!", p2.InnerText);
}
// Act.
SearchAndReplace(docxStream);
// Assert.
using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(docxStream, false))
{
MainDocumentPart part = wordDocument.MainDocumentPart;
Paragraph p1 = part.Document.Descendants<Paragraph>().First();
Paragraph p2 = part.Document.Descendants<Paragraph>().Last();
Assert.Equal("Hi Everyone!", p1.InnerText);
Assert.Equal("Hello world!", p2.InnerText);
}
}
private static void SearchAndReplace(MemoryStream docxStream)
{
using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(docxStream, true))
{
// If you wanted to read the part's contents as text, this is how you
// would do it.
string partText = ReadPartText(wordDocument.MainDocumentPart);
// Note that this is not the way in which you should search and replace
// text in Open XML documents. The text might be split across multiple
// w:r elements, so you would not find the text in that case.
var regex = new Regex("Hello world!");
partText = regex.Replace(partText, "Hi Everyone!");
// If you wanted to write changed text back to the part, this is how
// you would do it.
WritePartText(wordDocument.MainDocumentPart, partText);
}
docxStream.Seek(0, SeekOrigin.Begin);
}
private static string ReadPartText(OpenXmlPart part)
{
using Stream partStream = part.GetStream(FileMode.OpenOrCreate, FileAccess.Read);
using var sr = new StreamReader(partStream);
return sr.ReadToEnd();
}
private static void WritePartText(OpenXmlPart part, string text)
{
using Stream partStream = part.GetStream(FileMode.Create, FileAccess.Write);
using var sw = new StreamWriter(partStream);
sw.Write(text);
}
The File class in the dart:io library doesn't yet include copy() and move() methods.
To tide me over until they arrive, I'm trying to roll my own copy function. I'm using the code below on Windows, but it just creates a 0kb file.
void copyFile(String input, String output) {
var inFile = new File(input), outFile = new File(output);
if (outFile.existsSync()) outFile.deleteSync(); // I realize this isn't required
var inStream = null, outStream = null;
try {
inStream = inFile.openInputStream();
outStream = outFile.openOutputStream(FileMode.WRITE);
inStream.pipe(outStream);
} finally {
if (outStream != null && !outStream.closed) outStream.close();
if (inStream != null && !inStream.closed) inStream.close();
}
}
I've also tried replacing the pipe line with print(inStream.read(100).toString()); and I get null. The input file does exist (otherwise I'd get a FileIOException). Am I doing something wrong, or are input streams broken under Windows?
I'm using:
Dart Editor version 0.3.1_r17463
Dart SDK version 0.3.1.2_r17463
Edit: The following works (although it doesn't "chunk"). Am I using the streams above incorrectly?
void copyFile(String input, String output) {
var inFile = new File(input), outFile = new File(output);
if (outFile.existsSync()) outFile.deleteSync(); // I realize this isn't required
outFile.writeAsBytesSync(inFile.readAsBytesSync(), FileMode.WRITE);
}
With your first code snippet, you get an empty file because pipe is not a synchronous method. Thus, the copy of inputStream to outputStream has not started when the finally block is execute. By closing the streams in this finally block, you stop the pipe before it even starts. Without that finally block the copy is done correctly.
void copyFile(String input, String output) {
final inStream = new File(input).openInputStream();
final outStream = new File(output).openOutputStream(FileMode.WRITE);
inStream.pipe(outStream);
}
Finally, you don't have to worry about closing streams because pipe close streams by default once achieved. See InputStream.pipe.
For synchronous copy, use:
File(sourceFile).copySync(destinationFile);
For asynchronous copy, use:
File(sourceFile).copy(destinationFile);
I'm a bit new to WinRT developing platform, and it's already driving me crazy (I'm a long-time .Net developer, and all those removed APIs are quite annoying)
I'm experiencing a problem while zipping all files present in the Windows.Storage.ApplicationData.Current.TemporaryFolder
Here is my current code (VB.Net, based on MSDN code, and "file" is the zip file I'll put all my files into) :
Using zipMemoryStream As New MemoryStream()
Using zipArchive As New Compression.ZipArchive(zipMemoryStream, Compression.ZipArchiveMode.Create)
For Each fileToCompress As Windows.Storage.StorageFile In (Await Windows.Storage.ApplicationData.Current.TemporaryFolder.GetFilesAsync())
Dim buffer As Byte() = WindowsRuntimeBufferExtensions.ToArray(Await Windows.Storage.FileIO.ReadBufferAsync(fileToCompress))
Dim entry As ZipArchiveEntry = zipArchive.CreateEntry(fileToCompress.Name)
Using entryStream As Stream = entry.Open()
Await entryStream.WriteAsync(buffer, 0, buffer.Length)
End Using
Next
End Using
Using zipStream As Windows.Storage.Streams.IRandomAccessStream = Await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite)
Using outstream As Stream = zipStream.AsStreamForWrite()
Dim buffer As Byte() = zipMemoryStream.ToArray()
outstream.Write(buffer, 0, buffer.Length)
outstream.Flush()
End Using
End Using
End Using
It builds well, but when I launch the code, I have the exception :
UnauthorizedAccessException : Access denied. (Exception de HRESULT : 0x80070005 (E_ACCESSDENIED))
On line : WindowsRuntimeBufferExtensions.ToArray(blahblah...
I'm wondering what is wrong. Any idea ?
Thanks in advance !
I rewrote your method in C# to try it out:
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("test.zip");
using (var zipMemoryStream = new MemoryStream())
{
using (var zipArchive = new System.IO.Compression.ZipArchive(zipMemoryStream, System.IO.Compression.ZipArchiveMode.Create))
{
foreach (var fileToCompress in (await ApplicationData.Current.TemporaryFolder.GetFilesAsync()))
{
var buffer = WindowsRuntimeBufferExtensions.ToArray(await FileIO.ReadBufferAsync(fileToCompress));
var entry = zipArchive.CreateEntry(fileToCompress.Name);
using (var entryStream = entry.Open())
{
await entryStream.WriteAsync(buffer, 0, buffer.Length);
}
}
}
using ( var zipStream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
{
using (var outstream = zipStream.AsStreamForWrite())
{
var buffer = zipMemoryStream.ToArray();
outstream.Write(buffer, 0, buffer.Length);
outstream.Flush();
}
}
}
It works flawlessly - it creates the zip file in local folder as expected. Since you get the exception in ToArray call, the reason could be that the file you're trying to open is already locked from somewhere else. If you are creating these files yourself or even only accessing them, make sure you're closing the streams.
To test this method you could manually create a folder inside temp folder, put a couple of files in it and then run the method on that folder (the files are in C:\Users\<Username>\AppData\Local\Packages\<PackageName>\TempState) just to exclude any other reason for error.
In a Windows 8 Metro application written in JS I open a file, get the stream, write some image data to it using the 'promise - .then' pattern. It works fine - the file is successfully saved to the file system, except after using the BitmapEncoder to flush the stream to the file, the stream is still open. ie; I can't access the file until I kill the application, but the 'stream' variable is out of scope for me to reference, so I can't close() it. Is there something comparable to the C# using statement that could be used?
...then(function (file) {
return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
})
.then(function (stream) {
//Create imageencoder object
return Imaging.BitmapEncoder.createAsync(Imaging.BitmapEncoder.pngEncoderId, stream);
})
.then(function (encoder) {
//Set the pixel data in the encoder ('canvasImage.data' is an existing image stream)
encoder.setPixelData(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, canvasImage.width, canvasImage.height, 96, 96, canvasImage.data);
//Go do the encoding
return encoder.flushAsync();
//file saved successfully,
//but stream is still open and the stream variable is out of scope.
};
This simple imaging sample from Microsoft might help. Copied below.
It looks like, in your case, you need to declare the stream before the chain of then calls, make sure you don't name-collide with your parameter to your function accepting the stream (note the part where they do _stream = stream), and add a then call to close the stream.
function scenario2GetImageRotationAsync(file) {
var accessMode = Windows.Storage.FileAccessMode.read;
// Keep data in-scope across multiple asynchronous methods
var stream;
var exifRotation;
return file.openAsync(accessMode).then(function (_stream) {
stream = _stream;
return Imaging.BitmapDecoder.createAsync(stream);
}).then(function (decoder) {
// irrelevant stuff to this question
}).then(function () {
if (stream) {
stream.close();
}
return exifRotation;
});
}