This is the code below (C#) To upload in https://nft.storage/ It Works fine But when I upload mp4 file (Uploaded successfully) , The uploaded file doesn’t work . Source Code https://github.com/filipepolizel/unity-nft-storage
I used many different HTTPCLIENT example but it same
broken Uploaded mp4 File: http://ipfs.io/ipfs/bafybeibt4jqvncw6cuyih27mujbpdmsjl46pykablvravh3qg63vuvcdqy
// nft.storage API endpoint
private static readonly string nftStorageApiUrl = "https://api.nft.storage/";
// HTTP client to communicate with nft.storage
private static readonly HttpClient nftClient = new HttpClient();
// http client to communicate with IPFS API
private static readonly HttpClient ipfsClient = new HttpClient();
// nft.storage API key
public string apiToken;
void Start()
{
nftClient.DefaultRequestHeaders.Add("Accept", "application/json");
if (apiToken != null)
{
nftClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + apiToken);
}
else
{
// log in console in case no API key is found during initialization
Debug.Log("Starting NFT Storage Client without API key, please call 'SetApiToken' method before using class methods.");
}
}
public async Task<NFTStorageUploadResponse> UploadDataFromFile(string path)
{
StreamReader reader = new StreamReader(path);
string data = reader.ReadToEnd();
reader.Close();
print("Uploading...");
return await UploadDataFromString(data);
}
public async Task<NFTStorageUploadResponse> UploadDataFromString(string data)
{
string requestUri = nftStorageApiUrl + "/upload";
string rawResponse = await Upload(requestUri, data);
NFTStorageUploadResponse parsedResponse = JsonUtility.FromJson<NFTStorageUploadResponse>(rawResponse);
return parsedResponse;
}
private async Task<string> Upload(string uri, string paramString)
{
try
{
using (HttpContent content = new StringContent(paramString))
{
//content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Headers.ContentType = new MediaTypeHeaderValue("*/*");
HttpResponseMessage response = await nftClient.PostAsync(uri, content);
response.EnsureSuccessStatusCode();
Stream responseStream = await response.Content.ReadAsStreamAsync();
StreamReader reader = new StreamReader(responseStream);
return reader.ReadToEnd();
}
}
catch (HttpRequestException e)
{
Debug.Log("HTTP Request Exception: " + e.Message);
Debug.Log(e);
return null;
}
}
the answer helped me . thanks , I changed the Update method to :
public static async Task<string> Upload(string uri, string pathFile)
{
byte[] bytes = System.IO.File.ReadAllBytes(pathFile);
using (var content = new ByteArrayContent(bytes))
{
content.Headers.ContentType = new MediaTypeHeaderValue("*/*");
//Send it
var response = await nftClient.PostAsync(uri, content);
response.EnsureSuccessStatusCode();
Stream responseStream = await response.Content.ReadAsStreamAsync();
StreamReader reader = new StreamReader(responseStream);
return reader.ReadToEnd();
}
}
It works great now
Related
I'm trying after "converted/optimized" a C# Unity Project to my Visual Studio in C# to work for me (the code)...
i used this github lib for nft.storage
https://github.com/filipepolizel/unity-nft-storage/blob/main/NFTStorageClient.cs
If i call then with:
string pathtofile = #"" + AppDomain.CurrentDomain.BaseDirectory + "testfile.txt";
await NFTStorageTest.Upload(NFTStorageTest.nftStorageApiUrl, pathtofile);
i get this error:
System.Net.Http.HttpRequestException: Response status code does not indicate success: 404 (Not Found). at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at Main.net.NFTStorageTest.Upload(String uri, String pathFile) in C:\...\NFTStorageTest.cs:line 173
Here is my Code:
// nft.storage API endpoint
internal static readonly string nftStorageApiUrl = "https://api.nft.storage/";
// HTTP client to communicate with nft.storage
internal static readonly HttpClient nftClient = new HttpClient();
// http client to communicate with IPFS API
internal static readonly HttpClient ipfsClient = new HttpClient();
// nft.storage API key
public string apiToken = "XXX";
public void Start()
{
nftClient.DefaultRequestHeaders.Add("Accept", "application/json");
if (apiToken != null)
{
nftClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + apiToken);
}
else
{
// log in console in case no API key is found during initialization
Console.WriteLine("Starting NFT Storage Client without API key, please call 'SetApiToken' method before using class methods.");
}
}
public async Task<NFTStorageUploadResponse> UploadDataFromFile(string path)
{
StreamReader reader = new StreamReader(path);
string data = reader.ReadToEnd();
reader.Close();
Console.WriteLine("Uploading...");
return await UploadDataFromString(data);
}
public async Task<NFTStorageUploadResponse> UploadDataFromString(string data)
{
string requestUri = nftStorageApiUrl + "/upload";
string rawResponse = await Upload(requestUri, data);
string jsonString = JsonConvert.SerializeObject(rawResponse);
NFTStorageUploadResponse parsedResponse = JsonConvert.DeserializeObject<NFTStorageUploadResponse>(jsonString);
return parsedResponse;
}
public static async Task<string> Upload(string uri, string pathFile)
{
byte[] bytes = File.ReadAllBytes(pathFile);
using (var content = new ByteArrayContent(bytes))
{
content.Headers.ContentType = new MediaTypeHeaderValue("*/*");
//Send it
var response = await nftClient.PostAsync(uri, content);
response.EnsureSuccessStatusCode();
Stream responseStream = await response.Content.ReadAsStreamAsync();
StreamReader reader = new StreamReader(responseStream);
return reader.ReadToEnd();
}
}`
whats my mistake and how can i fix it?
await NFTStorageTest.Upload(NFTStorageTest.nftStorageApiUrl, pathtofile);
This should be called with
$”{NFTStorageTest.nftStorageApiUrl}upload”
See the original file
https://github.com/filipepolizel/unity-nft-storage/blob/45bedb5c421982645bc9bf49d12beed8f2cdb9d3/NFTStorageClient.cs#L297
I have a form on my website that makes a basic Get request to an API (managed by the client). It was working for years, until suddenly, it started throwing the error:
The underlying connection was closed: An unexpected error occurred on a send
I've had the client looking into the API, and aren't aware of anything that has changed on their server. Our code hasn't changed either. However, there must be something in the code that is affecting its ability to connect with the server, because I am able to make the Get request in the browser, through postman, and in a brand new console app that we created for testing. Both the website and console app are targeting .Net 4.6.2
Here is the complete code of the console app, which is exactly the same as what's being used within the form submission in my website (with the exception of that I hardcoded the querystring for testing):
internal class Program{
static void Main(string[] args){
url = "https://apiurl.com/api/UserSearch";
string webServiceUrl = url + "?email=test#yopmail.com";
var response = ServiceHelper.GetHttpWebRequest(webServiceUrl);
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream);
var jsonResponse = reader.ReadToEnd();
Console.WriteLine(jsonResponse);
}
}
}
public static class ServiceHelper
{
public static HttpWebResponse GetHttpWebRequest(string requestUrl, NameValueCollection requestHeaders = null)
{
var request = (HttpWebRequest)WebRequest.Create(requestUrl);
if (requestHeaders != null)
{
request.Headers.Add(requestHeaders);
}
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException wex)
{
Log.Error("ServiceHelper: Error getting Response Stream. "
+ Environment.NewLine + "RequestUrl = " + requestUrl
+ Environment.NewLine + GetWebExceptionDetails(wex), typeof(ServiceHelper));
throw;
}
string logMessage = "ServiceHelper: Called " + requestUrl;
if (response.StatusCode != HttpStatusCode.OK)
{
logMessage += " Response Status Code:" + response.StatusCode;
}
Log.Info(logMessage, typeof(ServiceHelper));
return response;
}
}
Since the basic code for the web request works in the console app, there must be something in the website configuration that's messing with the settings, but I'm not sure where to start looking.
EDIT: Alternate code that uses httpclient instead. This also works in console, fails in the website. Rather than immediately throwing an error, it just seems to hang in the async request indefinitely.
public static class httpclient
{
// uses asynchronous operations and await
public static async Task<string> Post(string url, string json)
{
// Encode the json data for HTTP
StringContent data = new StringContent(json, Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(url, data);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
public static async Task<string> Get(string url, string querystring)
{
var builder = new UriBuilder(url);
builder.Query = querystring;
var uri = builder.ToString();
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(uri);
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
}
internal class Program{
static void Main(string[] args){
string webServiceUrl = "https://apiurl.com/api/UserSearch";;
var querystring = "?email=" + email;
var result = httpclient.Get(webServiceUrl, querystring).GetAwaiter().GetResult();
console.log(results);
}
}
I get an error 400 Bad Request when I try to upload a file to my OneDrive using the Microsoft Graph API
GetAccessToken method get the access token
upload method take the file path and upload it to my OneDrive account
public class OneDrive
{
public void Upload(string filePath)
{
var token = GetAccessToken();
var url = "https://graph.microsoft.com/v1.0/drive/root:/test/test.pdf:/content";
PostRequest(url, token, filePath).Wait();
}
public string GetAccessToken()
{
var app = ConfidentialClientApplicationBuilder.Create("client id ")
.WithClientSecret("client secret")
.WithAuthority("https://login.microsoftonline.com/{tenant id}/v2.0")
.Build();
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
try
{
var result = app.AcquireTokenForClient(scopes).ExecuteAsync().Result;
Console.WriteLine(result.TenantId);
return result.AccessToken;
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
Console.WriteLine(ex.Message);
return null;
}
}
public async Task PostRequest(string webApiUrl, string accessToken, string filePath)
{
HttpContent content = new StreamContent(new MemoryStream(File.ReadAllBytes(filePath)));
HttpClient httpClient = new HttpClient();
if (!string.IsNullOrEmpty(accessToken))
{
var defaultRequestHeaders = httpClient.DefaultRequestHeaders;
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
defaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
HttpResponseMessage response = await httpClient.PutAsync(webApiUrl, content);
if (response.IsSuccessStatusCode)
Console.WriteLine("File Successfuly Uploaded");
else
Console.WriteLine("Error Occur");
}
}
}
After removing this line :
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
Your code works perfectly for me:
There is no need to set accpet header in request.
I have a .NET Core Web API project with a request and response logging middleware. I registered both middleware files in the Configure method in the Startup file
app.UseMiddleware<RequestLoggingMiddleware>();
app.UseMiddleware<ResponseLoggingMiddleware>();
For now I'm just trying to log the body, the request logging seems to work fine
public class RequestLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
public RequestLoggingMiddleware(RequestDelegate requestDelegate)
{
this.requestDelegate = requestDelegate;
}
public async Task InvokeAsync(HttpContext httpContext)
{
HttpRequest httpRequest = httpContext.Request;
httpRequest.EnableBuffering();
ReadResult bodyReadResult = await httpRequest.BodyReader.ReadAsync();
ReadOnlySequence<byte> bodyBuffer = bodyReadResult.Buffer;
if (bodyBuffer.Length > 0)
{
byte[] bodyBytes = bodyBuffer.ToArray();
string bodyText = Encoding.UTF8.GetString(bodyBytes);
Console.WriteLine(bodyText);
}
// Reset
httpRequest.Body.Seek(0, SeekOrigin.Begin);
await requestDelegate(httpContext);
}
}
My response logging middleware does not have access to a BodyReader. I tried to go with this code
public class ResponseLoggingMiddleware
{
private readonly RequestDelegate requestDelegate;
public ResponseLoggingMiddleware(RequestDelegate requestDelegate)
{
this.requestDelegate = requestDelegate;
}
public async Task InvokeAsync(HttpContext httpContext)
{
await requestDelegate(httpContext);
Stream responseBody = httpContext.Response.Body;
using (StreamReader reader = new StreamReader(responseBody))
{
string bodyText = await reader.ReadToEndAsync();
// Reset
responseBody.Seek(0, SeekOrigin.Begin);
Console.WriteLine(bodyText);
}
}
}
but unfortunately I get this exception
System.ArgumentException: Stream was not readable.
Does someone know how to fix it?
You may use StreamReader to read the request body. Below code, you may follow.
string body = string.Empty;
Request.EnableRewind();
using (var reader = new StreamReader(Request.Body))
{
Request.Body.Seek(0, SeekOrigin.Begin);
body = reader.ReadToEnd();
}
In the same way, you can get a response body.
using (var reader = new StreamReader(Response.Body))
{
Response.Body.Seek(0, SeekOrigin.Begin);
body = reader.ReadToEnd();
}
Notes: Above code is based on .net core 2.2
Below is the code supported by .net core 5
string body = string.Empty;
using (var reader = new StreamReader(Request.Body))
{
//Request.Body.Seek(0, SeekOrigin.Begin);
//body = reader.ReadToEnd();
body = await reader.ReadToEndAsync();
}
Now, you have the response in the body property, do your kinds of stuff (JSON Deserilize).
Stream is an Abstract class, you must tu use a MemoryStream, check this:
using (var ms = new MemoryStream())
{
var cuerpoOriginalRespuesta = contexto.Response.Body;
contexto.Response.Body = ms;
await siguiente(contexto);
ms.Seek(0, SeekOrigin.Begin);
string respuesta = new StreamReader(ms).ReadToEnd();
ms.Seek(0, SeekOrigin.Begin);
await ms.CopyToAsync(cuerpoOriginalRespuesta);
contexto.Response.Body = cuerpoOriginalRespuesta;
}
Anyone who is looking for the solution of .net standard can use the following snippet
For ApiController
string requestBody = string.Empty;
using (var reader = new StreamReader(HttpContext.Current.Request.InputStream))
{
reader.BaseStream.Seek(0, SeekOrigin.Begin);
requestBody = reader.ReadToEnd();
}
Console.WriteLine(requestBody);
For regular controller
string requestBody = string.Empty;
using (var reader = new StreamReader(HttpContext.Request.InputStream))
{
reader.BaseStream.Seek(0, SeekOrigin.Begin);
requestBody = reader.ReadToEnd();
}
Console.WriteLine(requestBody);
I'm currently using Pushbullet API and need to upload a file.
I can successfully get an upload url as specified in the docs using this method:
public static async Task<Uploads> GetUploadUrl(string file_name, string file_type)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var json = new JObject
{
["file_name"] = file_name,
["file_type"] = file_type
};
var result = await client.PostAsync(new Uri(_uploadUrl, UriKind.RelativeOrAbsolute), new HttpStringContent(json.ToString(), UnicodeEncoding.Utf8, "application/json"));
if (result.IsSuccessStatusCode)
{
var textresult = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Uploads>(textresult);
}
}
return null;
}
The problem is when I try to upload the file. I'm currently using this method:
public static async Task<bool> UploadFile(StorageFile file, string upload_url)
{
try
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var content = new MultipartFormDataContent();
if (file != null)
{
var streamData = await file.OpenReadAsync();
var bytes = new byte[streamData.Size];
using (var dataReader = new DataReader(streamData))
{
await dataReader.LoadAsync((uint)streamData.Size);
dataReader.ReadBytes(bytes);
}
var streamContent = new ByteArrayContent(bytes);
content.Add(streamContent);
}
client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var response = await client.PostAsync(new Uri(upload_url, UriKind.Absolute), content);
if (response.IsSuccessStatusCode)
return true;
}
catch { return false; }
return false;
}
but I get a Http 400 error. What's the right way to upload a file using multipart/form-data in a UWP app?
HTTP 400 error indicates Bad Request, it means the request could not be understood by the server due to malformed syntax. In the other word, the request sent by the client doesn't follow server's rules.
Let's look at the document, and we can find in the example request it uses following parameter:
-F file=#cat.jpg
So in the request, we need to set the name for the uploaded file and the name should be "file". Besides, in this request, there is no need to use access token. So you can change your code like following:
public static async Task<bool> UploadFile(StorageFile file, string upload_url)
{
try
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var content = new MultipartFormDataContent();
if (file != null)
{
var streamData = await file.OpenReadAsync();
var bytes = new byte[streamData.Size];
using (var dataReader = new DataReader(streamData))
{
await dataReader.LoadAsync((uint)streamData.Size);
dataReader.ReadBytes(bytes);
}
var streamContent = new ByteArrayContent(bytes);
content.Add(streamContent, "file");
}
//client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var response = await client.PostAsync(new Uri(upload_url, UriKind.Absolute), content);
if (response.IsSuccessStatusCode)
return true;
}
catch { return false; }
return false;
}
Then your code should be able to work. You will get a 204 No Content response and UploadFile method will return true.