I'm Learning Blazor + WEB API. In the client project, I get all the data from the server into the view, except for the image.
Failed to load resource: the server responded with a status of 404 ()
It's my file upload service:
public async Task<string> UploadFile(Stream msFile, string pictureName)
{
var path = $"{_env.WebRootPath}\\images\\{pictureName}";
var buffer = new byte[4 * 1096];
int bytesRead;
double totalRead = 0;
using FileStream fs = new FileStream(path, FileMode.Create);
while ((bytesRead = await msFile.ReadAsync(buffer)) != 0)
{
totalRead += bytesRead;
await fs.WriteAsync(buffer);
}
var url = $"{_httpContextAccessor.HttpContext.Request.Scheme}://{_httpContextAccessor.HttpContext.Request.Host.Value}/";
var fullPath = $"{url}images/{pictureName}";
return fullPath;
}
My razor component
#foreach (var prod in item.Products)
{
<img class="d-block w-100" style="border-radius:20px;"
src="#prod.Image">
}
GitHub https://github.com/ValencyJacob/PharmacyStore
The image value you set below is just the name, but I find your stored static file and client are located in different project:
var pictureName = $"{pictureId}{ext}";
await _fileUpload.UploadFile(msFile, pictureName);
Model.Image = pictureName;
You need set the value with the full path(e.g: The Image value should be setted like : https://localhost:44375/images/04c91d389a8946d7b741b5a11eb73cfc.jpg):
var pictureName = $"{pictureId}{ext}";
var fullpath = await _fileUpload.UploadFile(msFile, pictureName);
Model.Image = fullpath;
Then you could display the images(store in PharmacyStore.UI) in another project(Client.WASM).
Note:
The port number(44375) should belong to the project which store the static file(PharmacyStore.UI).
Related
can I set a post method to post image and list of object in the same time I have the following code it's logically working but I'm trying to test this request with postman
private ApplicationDbContext1 db = new ApplicationDbContext1();
[Route("api/save_BUY")]
[HttpPost]
public async Task< IHttpActionResult> save_BUY(IEnumerable<BY_table> BY_table,int id)
{
var BY_API = BY_table.Select(p => new BY_API
{
ITEM_CODE = p.ITEM_CODE,
ITEM_NAME = p.ITEM_NAME,
Unit = p.Unit,
Unit_Core = Convert.ToDecimal(p.Unit_Core),
}).AsQueryable();
var ctx = HttpContext.Current;
var root = ctx.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.FileData)
{
var name = file.Headers
.ContentDisposition
.FileName;
var localFileName = file.LocalFileName;
var filePath = Path.Combine(
root, "files", name);
byte[] fileBytes;
using (var fs = new FileStream(
PHOTO, FileMode.Open, FileAccess.Read))
{
fileBytes = new byte[fs.Length];
fs.Read(
fileBytes, 0, Convert.ToInt32(fs.Length));
}
var MASTER_BUY = db.MASTER_BUY.Where(x => x.int==id)
{
MASTER_BUY.image= fileBytes;
};
db.SaveChanges();
return Ok(BY_API);
}
}
how can I make this request in postman to test it.
pleas help.
You Can send Image Form of base64 String And Get String value from Client(Postman)
Image to Base 64 String
This is one Of Online tools for help you get base 64 string from file!
I am trying to create a .Net Standard "Client" class for uploading (sometimes very large) files to a Controller. I want to do this by breaking the file into chunks and uploading them one at a time. The intent is for other applications to use this instead of communicating directly to the Web Api.
I already have the Controller working. I've verified that it works using a Kendo-ui control which supports chunk-saving.
The issue I am having is that the IEnumerable<IFormFile> files parameter for my controller is always empty when posted from my client class
Controller
[Route("api/Upload")]
public ActionResult ChunkSave(IEnumerable<IFormFile> files, string metaData, Guid id)
{
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(metaData));
var serializer = new DataContractJsonSerializer(typeof(ChunkMetaData));
ChunkMetaData somemetaData = serializer.ReadObject(ms) as ChunkMetaData;
// The Name of the Upload component is "files"
if (files != null)
{
// If this is the first chunk, try to delete the file so that we don't accidently
// and up appending new bytes to the old file.
if (somemetaData.ChunkIndex == 0)
{
_io.DeleteFile(id, Path.GetFileName(somemetaData.FileName));
}
foreach (var file in files)
{
// Some browsers send file names with full path. This needs to be stripped.
_io.AppendToFile(id, Path.GetFileName(somemetaData.FileName), file.OpenReadStream());
}
}
FileResult fileBlob = new FileResult();
fileBlob.uploaded = somemetaData.TotalChunks - 1 <= somemetaData.ChunkIndex;
fileBlob.fileUid = somemetaData.UploadUid;
return new JsonResult(fileBlob);
}
Client:
public class FileTransferClient
{
HttpClient Client { get; set; }
public FileTransferClient(Uri apiUrl)
{
this.Client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true })
{
BaseAddress = apiUrl
};
this.Client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<bool> UploadFile(Guid id, Stream file, string name, string contentType)
{
bool ret = true;
int chunckSize = 2097152; //2MB
int totalChunks = (int)(file.Length / chunckSize);
if (file.Length % chunckSize != 0)
{
totalChunks++;
}
for (int i = 0; i < totalChunks; i++)
{
long position = (i * (long)chunckSize);
int toRead = (int)Math.Min(file.Length - position + 1, chunckSize);
byte[] buffer = new byte[toRead];
await file.ReadAsync(buffer, 0, toRead);
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StringContent(id.ToString()), "id");
var meta = JsonConvert.SerializeObject(new ChunkMetaData
{
UploadUid = id.ToString(),
FileName = name,
ChunkIndex = i,
TotalChunks = totalChunks,
TotalFileSize = file.Length,
ContentType = contentType
});
content.Add(new StringContent(meta), "metaData");
using (var ms = new MemoryStream(buffer))
{
content.Add(new StreamContent(ms),"files");
var response = await Client.PostAsync("/api/Upload", content).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
ret = false;
break;
}
}
}
return ret;
}
}
Your param is empty, because you're not sending an array of files, but rather just one file. Therefore, the binding fails, and you get a null. The act of chunking (which you aren't actually even doing) does not equate to an IEnumerable<IFormFile>; it's still just an IFormFile.
While you need to send as multipart/form-data because you're sending both a file upload and some other post data, I think you're misunderstanding what this actually does. It simply means the request body contains multiple different mime-types, it does not mean that it's uploading the file in multiple parts, which seems to be what you're thinking it does.
The actual act of streaming the upload occurs on the server-side. It's about how the server chooses to handle the file being uploaded, and not so much about how the user is uploading it. More specifically, any sort of modelbinding, particular to an IFormFile will cause the file to be spooled to disk first, and then passed into your action. In other words, if you're accepting an IFormFile, you've already lost the battle. It's already been fully transferred from the client to your server.
The ASP.NET Core docs show you how to actually stream the upload, and unsurprisingly there's a fair bit of code involved, none of which you have currently. You basically have to turn modelbinding off entirely on the action and manually parse the request body yourself, being careful to actually chunk the reads from the stream and not do something that will force the entirely thing into memory at once.
The issue was that I was using a StreamContent instead of a ByteArrayContent to represent my file chunks. Here's what I ended up with:
public async Task<Bool> UploadFileAsync(Guid id, string name, Stream file)
{
int chunckSize = 2097152; //2MB
int totalChunks = (int)(file.Length / chunckSize);
if (file.Length % chunckSize != 0)
{
totalChunks++;
}
for (int i = 0; i < totalChunks; i++)
{
long position = (i * (long)chunckSize);
int toRead = (int)Math.Min(file.Length - position, chunckSize);
byte[] buffer = new byte[toRead];
await file.ReadAsync(buffer, 0, buffer.Length);
using (MultipartFormDataContent form = new MultipartFormDataContent())
{
form.Add(new ByteArrayContent(buffer), "files", name);
form.Add(new StringContent(id.ToString()), "id");
var meta = JsonConvert.SerializeObject(new ChunkMetaData
{
UploadUid = id.ToString(),
FileName = name,
ChunkIndex = i,
TotalChunks = totalChunks,
TotalFileSize = file.Length,
ContentType = "application/unknown"
});
form.Add(new StringContent(meta), "metaData");
var response = await Client.PostAsync("/api/Upload", form).ConfigureAwait(false);
return response.IsSuccessStatusCode;
}
}
return true;
}
I'm using the new Dropbox SDK v2 for .NET.
I'm trying to upload a document to a Dropbox account.
public async Task UploadDoc()
{
using (var dbx = new DropboxClient("XXXXXXXXXX"))
{
var full = await dbx.Users.GetCurrentAccountAsync();
await Upload(dbx, #"/MyApp/test", "test.txt","Testing!");
}
}
async Task Upload(DropboxClient dbx, string folder, string file, string content)
{
using (var mem = new MemoryStream(Encoding.UTF8.GetBytes(content)))
{
var updated = await dbx.Files.UploadAsync(
folder + "/" + file,
WriteMode.Overwrite.Instance,
body: mem);
Console.WriteLine("Saved {0}/{1} rev {2}", folder, file, updated.Rev);
}
}
This code snippet actually creates a test.txt document on the Dropbox account with the "Testing!" content, but I want to upload a document, with a given path (for example: "C:\MyDocuments\test.txt"), is that possible?
Any help would be very much appreciated.
The UploadAsync method will use whatever data you pass to the body parameter as the uploaded file content.
If you want to upload the contents of a local file, you'll need to give it a stream for that file.
There's an example here that shows how to use this method to upload a local file (including logic for handling large files):
This example uses the Dropbox .NET library to upload a file to a Dropbox account, using upload sessions for larger files:
private async Task Upload(string localPath, string remotePath)
{
const int ChunkSize = 4096 * 1024;
using (var fileStream = File.Open(localPath, FileMode.Open))
{
if (fileStream.Length <= ChunkSize)
{
await this.client.Files.UploadAsync(remotePath, body: fileStream);
}
else
{
await this.ChunkUpload(remotePath, fileStream, (int)ChunkSize);
}
}
}
private async Task ChunkUpload(String path, FileStream stream, int chunkSize)
{
ulong numChunks = (ulong)Math.Ceiling((double)stream.Length / chunkSize);
byte[] buffer = new byte[chunkSize];
string sessionId = null;
for (ulong idx = 0; idx < numChunks; idx++)
{
var byteRead = stream.Read(buffer, 0, chunkSize);
using (var memStream = new MemoryStream(buffer, 0, byteRead))
{
if (idx == 0)
{
var result = await this.client.Files.UploadSessionStartAsync(false, memStream);
sessionId = result.SessionId;
}
else
{
var cursor = new UploadSessionCursor(sessionId, (ulong)chunkSize * idx);
if (idx == numChunks - 1)
{
FileMetadata fileMetadata = await this.client.Files.UploadSessionFinishAsync(cursor, new CommitInfo(path), memStream);
Console.WriteLine (fileMetadata.PathDisplay);
}
else
{
await this.client.Files.UploadSessionAppendV2Async(cursor, false, memStream);
}
}
}
}
}
You can use the following method if you just want to upload a file with a given path:
private async Task Upload(DropboxClient dbx, string folder, string file, string fileToUpload)
{
using (var mem = new MemoryStream(File.ReadAllBytes(fileToUpload)))
{
var updated = await dbx.Files.UploadAsync(
folder + "/" + file,
WriteMode.Overwrite.Instance,
body: mem);
Console.WriteLine("Saved {0}/{1} rev {2}", folder, file, updated.Rev);
}
}
Parameter example:
folder = "/YourDropboxFolderName";
file = "fileName.pdf";
fileToUpload = #"C:\Users\YourUserName\fileName.pdf";
I am trying to set the thumbnail for a pull video upload done through the vimeo api. I am developing this for a c# windows service and please note that there are no official libraries for this. For the moment I use this library. I am able to successfully upload the video by following the vimeo documentation, however, when I try to upload an image to be the thumbnail of a video I get an issue. According to the vimeo picutre upload documentation, in step 2, i need to upload my thumbnail image via a PUT request. It says, that I need to do the following:
PUT https://i.cloud.vimeo.com/video/518016424
.... binary data of your file in the body ....
I can't figure out how to do this. I can get the binary data of the image by using
byte[] byte_array_of_image = File.ReadAllBytes(file);
but how can I send this data to the api and get a response (with or without using the library)? If it would help, here is my code to upload the video and thumbnail done so far.
var vc = VimeoClient.ReAuthorize(
accessToken: ConfigurationManager.AppSettings["ACCESS_TOKEN"],
cid: ConfigurationManager.AppSettings["API_KEY"],
secret: ConfigurationManager.AppSettings["API_SECRET"]
);
string temporary_video_dir = ConfigurationManager.AppSettings["TEMP_VIDEO_URL"];
Dictionary<string,string> automatic_pull_parameters = new Dictionary<string, string>();
automatic_pull_parameters.Add("type", "pull");
automatic_pull_parameters.Add("link", temporary_video_dir);
var video_upload_request = vc.Request("/me/videos", automatic_pull_parameters, "POST");
string uploaded_URI = video_upload_request["uri"].ToString();
string video_id = uploaded_URI.Split('/')[2];
Library.WriteErrorLog("Succesfully uploaded Video in test folder. Returned Vimeo ID for video: "+ video_id);
var picture_resource_request = vc.Request("/videos/" + video_id + "/pictures", null, "POST");
string picture_resource_link = picture_resource_request["uri"].ToString();
//Library.WriteErrorLog("uri: " + picture_resource_link);
byte[] binary_image_data = File.ReadAllBytes("http://testclient.xitech.com.au/Videos/Images/Closing_2051.jpg");
string thumbnail_upload_link = picture_resource_link.Split('/')[4];
Please help! Stuck for hours now.
WebClient has a method called UploadData that fits like a glove. Below there is an example that what you can do.
WebClient wb = new WebClient();
wb.Headers.Add("Authorization","Bearer" +AccessToken);
var file = wb.DownloadData(new Uri("http://testclient.xitech.com.au/Videos/Images/Closing_2051.jpg"));
var asByteArrayContent = wb.UploadData(new Uri(picture_resource_request ), "PUT", file);
var asStringContent = Encoding.UTF8.GetString(asByteArrayContent);
reference post:- Vimeo API C# - Uploading a video
the answer is not upvoted but it could be tried worked well in my case.
see the code below:-
public ActionResult UploadChapterVideoVimeo(HttpPostedFileBase file, string productID = "")
{
if (file != null){
var authCheck = Task.Run(async () => await vimeoClient.GetAccountInformationAsync()).Result;
if (authCheck.Name != null)
{
BinaryContent binaryContent = new BinaryContent(file.InputStream, file.ContentType);
int chunkSize = 0;
int contenetLength = file.ContentLength;
int temp1 = contenetLength / 1024;
if (temp1 > 1)
{
chunkSize = temp1 / 1024;
chunkSize = chunkSize * 1048576;
}
else
{ chunkSize = chunkSize * 1048576; }
binaryContent.OriginalFileName = file.FileName;
var d = Task.Run(async () => await vimeoClient.UploadEntireFileAsync(binaryContent, chunkSize, null)).Result;
vmodel.chapter_vimeo_url = "VIMEO-" + d.ClipUri;
}
return RedirectToAction("ProductBuilder", "Products", new { productId = EncryptedProductID, message = "Successfully Uploaded video", type = 1 });
}
}
catch (Exception exc)
{
return RedirectToAction("ProductBuilder", "Products", new { productId = EncryptedProductID, message = "Failed to Uploaded video " + exc.Message, type = 0 });
}
}
return null; }
I am using FileStream.Create to upload a .csv file onto a server and then read it into a SQL database. Once it is read in, I just delete the file from the folder that it was written to. The goal is to just get the file into the database. This would run fine locally, but I cannot get write access on the new server so I get an UnauthorizedAccessException. I don't think that it is necessary to upload the file to the server to read it into the SQL table, but I am having trouble adjusting the code.
[HttpPost]
public ActionResult UploadValidationTable(HttpPostedFileBase csvFile)
{
var inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true
};
var cc = new CsvContext();
var filePath = uploadFile(csvFile.InputStream);
var model = cc.Read<Credit>(filePath, inputFileDescription);
try
{
var entity = new Entities();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload
{
Id = item.Id,
Amount = item.Amount,
Date = item.Date,
Number = item.Number,
ReasonId = item.ReasonId,
Notes = item.Notes
};
entity.TemporaryCsvUploads.Add(tc);
}
entity.SaveChanges();
System.IO.File.Delete(filePath);
Here is the uploadFile method:
private string uploadFile(Stream serverFileStream)
{
const string directory = "~/Content/CSVUploads";
var directoryExists = Directory.Exists(Server.MapPath(directory));
if (!directoryExists)
{
Directory.CreateDirectory(Server.MapPath(directory));
}
var targetFolder = Server.MapPath(directory);
var filename = Path.Combine(targetFolder, Guid.NewGuid() + ".csv");
try
{
const int length = 256;
var buffer = new byte[length];
// write the required bytes
using (var fs = new FileStream(filename, FileMode.Create))
{
int bytesRead;
do
{
bytesRead = serverFileStream.Read(buffer, 0, length);
fs.Write(buffer, 0, bytesRead);
} while (bytesRead == length);
}
serverFileStream.Dispose();
return filename;
}
catch (Exception)
{
return string.Empty;
}
}
To sum it up, I am uploading a .csv file to a temporary location, reading it into an object, reading it into a database, then deleting the .csv file out of the temporary location. I am using Linq2Csv to create the object. Can I do this without uploading the file to the server (because I can't get write access)?
According to http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library,
you can read from a StreamReader
Read<T>(StreamReader stream)
Read<T>(StreamReader stream, CsvFileDescription fileDescription)
You can probably use a streamreader (or a stringbuilder) to create your file instead of a csv - Write StringBuilder to Stream
How to take a stringbuilder and convert it to a streamReader?
and then send that to your CSVContext?