I'm trying to build an application in which a user can upload a csv file and convert it into XML. Currently my controller can create .txt file in a temp folder. However when I open the txt file it comes out all corrupted as below:
I have two questions
1. How can I make it so that the file displays properly i.e. as items separated by commas?
2. How can I change my code to make the file upload into my solution explorer
Here is the relevant controller code:
[HttpPost("UploadFiles")]
public async Task<IActionResult> FileUpload(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);
var filePaths = new List<string>();
foreach (var formFile in files)
{
if(formFile.Length > 0)
{
var filePath = Path.GetTempPath()+ Guid.NewGuid().ToString()+".txt";
filePaths.Add(filePath);
using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite))
{
await formFile.CopyToAsync(stream);
}
}
}
return Ok(new { count = files.Count, size, filePaths });
}
Any suggestions would be much appreciated
Thanks in advance
When the file is corrupt I think the conversion doesn't work. Try for now uploading it without any conversion.
For the second question you can do the following
var filePath = Path.Combine(AppContext.BaseDirectory, $"{Guid.NewGuid().ToString()}.csv"); // or whatever extension you are actually having without modifying the original extension
This will store the file either in the "bin" directory path or in the directory where the source-code is located.
Related
my field is
public IFormFileCollection FileNames { get; set; }
i get multiple file from postman (form-data) and post
in api-controller i get fields of send with postman
my problem here,i need to path of files, how i can get path of FromFile?
updated code :
using (var fileStream = new FileStream(fileName.FileName, FileMode.Create,FileAccess.Write))
{
await fileName.CopyToAsync(fileStream);
fileStream.Dispose();
var request = MyOperationOnFile(fileStream.Name);
...
}
get this exception for second file(first file is ok):
"Cannot access a disposed object.\r\nObject name: 'FileBufferingReadStream'."
if dont use .dispose() get this exception for first file :
Failed to send: Microsoft.AspNetCore.Http.FormFile, with error:The process cannot access the file 'porjectLocation\file' because it is being used by another process
In fact, if you want to upload files, you do not need to know the original path of the files, but only need to create the path you need to upload.
The following is a case of uploading multiple files, please refer to it:
[HttpPost("UploadFile")]
public async Task<IActionResult> UploadFile(IFormFileCollection files)
{
foreach (var fileName in files)
{
var filesPath = Directory.GetCurrentDirectory() + "/Uploadfiles";
if (!System.IO.Directory.Exists(filesPath))//create path
{
Directory.CreateDirectory(filesPath);
}
var path = Path.Combine(filesPath, Path.GetFileName(fileName.FileName));//the path to upload
await fileName.CopyToAsync(new FileStream(path, FileMode.Create));
}
return Ok();
}
Here is the result:
The form file that you received from the request are actually the stream in memory of the files, you will need to save it on the disk or on your database. Check the examples in the documentation:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1
I'm collecting all my files in a target directory and adding them to a zip folder. Once this zip is made and no more files need adding to it, I want to move this zip folder to another location.
Here is my code for doing all of the above:
var targetFolder = Path.Combine(ConfigurationManager.AppSettings["targetFolder"], "Inbound");
var archiveFolder = ConfigurationManager.AppSettings["ArchiveFolder"];
// get files
var files = Directory.GetFiles(targetFolder)
.Select(f => new FileInfo(f))
.ToList();
// places files into zip
using (var zip = ZipFile.Open("file.zip", ZipArchiveMode.Create))
{
foreach (var file in files)
{
var entry = zip.CreateEntry(file.Name);
entry.LastWriteTime = DateTimeOffset.Now;
using (var stream = File.OpenRead(file.ToString()))
using (var entryStream = entry.Open())
stream.CopyTo(entryStream);
}
}
// move the zip file
File.Move("file.zip", archiveFolder );
Where I'm falling down is the moving of the zip folder. When my code gets to File.Move I get an error telling me it can not create something that already exists. This happen even when I hard code in my archive folder location instead of getting it from my config.
What am I doing wrong with this?
You need to specify the destination file name as well as directory:
File.Move("file.zip", Path.Combine(archiveFolder, "file.zip"));
I'll explain the problem right away, but first of all...is this achievable?
I have a Document Type in Umbraco where I store data from a Form. I can store everything except the file.
...
content.SetValue("notes", item.Notes);
content.SetValue("curriculum", item.Curriculum); /*this is the file*/
...
I'm adding items like this where SetValue comes from the following namespace namespace Umbraco.Core.Models and this is the function signature void SetValue(string propertyTypeAlias, object value)
And the return error is the following
"String or binary data would be truncated.
↵The statement has been terminated."
Did I missunderstood something? Shouldn't I be sending the base64? I'm adding the image to a media file where it creates a sub-folder with a sequential number. If I try to add an existing folder it appends the file just fine but if I point to a new media sub-folder it also returns an error. Any ideas on how should I approach this?
Thanks in advance
Edit 1: After Cryothic answer I've updated my code with the following
byte[] tempByte = Convert.FromBase64String(item.Curriculum);
var mediaFile = _mediaService.CreateMedia(item.cvExtension, -1, Constants.Conventions.MediaTypes.File);
Stream fileStream = new MemoryStream(tempByte);
var fileName = Path.GetFileNameWithoutExtension(item.cvExtension);
mediaFile.SetValue("umbracoFile", fileName, fileStream);
_mediaService.Save(mediaFile);
and the error happens at mediaFile.SetValue(...).
If I upload a file from umbraco it goes to "http://localhost:3295/media/1679/test.txt" and the next one would go to "http://localhost:3295/media/1680/test.txt". Where do I tell on my request that it has to add to the /media folder and increment? Do I only point to the media folder and umbaco handles the incrementation part?
If I change on SetValue to the following mediaFile.SetValue("curriculum", fileName, fileStream); the request succeeds but the file is not added to the content itself and the file is added to "http://localhost:3295/umbraco/media" instead of "http://localhost:3295/media".
If I try the following - content.SetValue("curriculum", item.cvExtension); - the file is added to the content but with the path "http://localhost:3295/umbraco/test.txt".
I'm not understanding very well how umbraco inserts files into the media folder (outside umbraco) and how you add the media service path to the content service.
Do you need to save base64?
I have done something like that, but using the MediaService.
My project had the option to upload multiple images on mulitple wizard-steps, and I needed to save them all at once. So I looped through the uploaded files (HttpFileCollection) per step. acceptedFiletypes is a string-list with the mimetypes I'd allow.
for (int i = 0; i < files.Count; i++) {
byte[] fileData = null;
UploadedFile uf = null;
try {
if (acceptedFiletypes.Contains(files[i].ContentType)) {
using (var binaryReader = new BinaryReader(files[i].InputStream)) {
fileData = binaryReader.ReadBytes(files[i].ContentLength);
}
if (fileData.Length > 0) {
uf = new UploadedFile {
FileName = files[i].FileName,
FileType = fileType,
FileData = fileData
};
}
}
}
catch { }
if (uf != null) {
projectData.UploadedFiles.Add(uf);
}
}
After the last step, I would loop throug my projectData.UploadedFiles and do the following.
var service = Umbraco.Core.ApplicationContext.Current.Services.MediaService;
var mediaTypeAlias = "Image";
var mediaItem = service.CreateMedia(fileName, parentFolderID, mediaTypeAlias);
Stream fileStream = new MemoryStream(file.FileData);
mediaItem.SetValue("umbracoFile", fileName, fileStream);
service.Save(mediaItem);
I also had a check which would see if the uploaded filename was ending on ".pdf". In that case I'd change the mediaTypeAlias to "File".
I hope this helps.
Here i have several images and i need to zip those images and need to download it..In here i use Ionzip.The problem is that zip is not working.It doen't shows me any error.
MyCode
public bool DownloadImgs()
{
string Path = HttpContext.Current.Server.MapPath("../Content/images/QImages");
string zippath = HttpContext.Current.Server.MapPath("../Content/images/QImages/zipped/");
string[] filenames = System.IO.Directory.GetFiles(Path, "*.jpg", SearchOption.AllDirectories);//It returns all the paths of the images.
using (ZipFile zip = new ZipFile())
{
foreach (String filename in filenames)
{
ZipEntry e = zip.AddFile(filename, "");
}
zip.Save(zippath);//In here i need to download the zipped file.not to save
}
}
PS: This application is built using MVC framework
You should write the resulting zip to the Response stream.
From a MVC controller:
return this.File(zippath, "application/zip");
From an ASP.NET handler or page:
Response.TransmitFile(zippath);
Another option is to directly save the zip file to the response stream, which will optimize your disk usage.
You can save your zip file straight to the response outputstream:
zipFile.Save(Response.OutputStream);
I am using DotNetZip.
What I need to do is to open up a zip files with files from the server.
The user can then grab the files and store it locally on their machine.
What I did before was the following:
string path = "Q:\\ZipFiles\\zip" + npnum + ".zip";
zip.Save(path);
Process.Start(path);
Note that Q: is a drive on the server. With Process.Start, it simply open up the zip file so that the user can access all the files. I like to do the same but not store the file on disk but show it from memory.
Now, instead of storing the zip file on the server, I like to open it up with MemoryStream
I have the following but does not seem to work
var ms = new MemoryStream();
zip.Save(ms);
but not sure how to proceed further in terms of opening up the zip file from a memory stream so that the user can access all the files
Here is a live piece of code (copied verbatim) which I wrote to download a series of blog posts as a zipped csv file. It's live and it works.
public ActionResult L2CSV()
{
var posts = _dataItemService.SelectStuff();
string csv = CSV.IEnumerableToCSV(posts);
// These first two lines simply get our required data as a long csv string
var fileData = Zip.CreateZip("LogPosts.csv", System.Text.Encoding.UTF8.GetBytes(csv));
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "LogPosts.zip",
// always prompt the user for downloading, set to true if you want
// the browser to try to show the file inline
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(fileData, "application/octet-stream");
}
You can use:
zip.Save(ms);
// Set read point to beginning of stream
ms.Position = 0;
ZipFile newZip = ZipFile.Read(ms);
See the documentation for Create a zip using content obtained from a stream.
using (ZipFile zip = new ZipFile())
{
ZipEntry e= zip.AddEntry("Content-From-Stream.bin", "basedirectory", StreamToRead);
e.Comment = "The content for entry in the zip file was obtained from a stream";
zip.AddFile("Readme.txt");
zip.Save(zipFileToCreate);
}
After saving it, you can then open it up as normal.