Google Drive Parse error when uploading file with special unicode characters - c#

A problem has occurred recently when trying to upload files with the Google API dotnet client sdk. When the file name has any special Unicode characters, it throws an error.
Here is my code
public static Google.Apis.Drive.v2.Data.File InsertResource(Google.Apis.Drive.v2.DriveService service, string filePath, string parentId, string fileName, string mimeType)
{
Google.Apis.Drive.v2.Data.File body = new Google.Apis.Drive.v2.Data.File();
try
{
// File's metadata.
body.Title = fileName;
body.MimeType = mimeType;
// Set the parent folder.
if (!String.IsNullOrEmpty(parentId))
{
var response = DriveUtils.GetFileInfo(service, parentId);
if (response.Error != null)
{
body.Error = response.Error;
return body;
}
body.Parents = new List<ParentReference>() { new ParentReference() { Id = parentId } };
}
byte[] byteArray = System.IO.File.ReadAllBytes(filePath);
MemoryStream stream = new MemoryStream(byteArray);
Google.Apis.Drive.v2.FilesResource.InsertMediaUpload request = service.Files.Insert(body, stream, mimeType);
request.Upload();
return request.ResponseBody;
}
catch (GoogleApiRequestException e)
{
body.Error = e.RequestError;
return body;
}
}
It was working fine up until this week. Any files that have chinese characters or turkish characters in the name will throw an error.
at Google.Apis.Json.JsonReader.ParseExpression(JsonToken token, TokenStream ts)
at Google.Apis.Json.JsonReader.Parse(String jsonAsText)
at Google.Apis.Upload.ResumableUpload`1.Upload()

Try to download the latest version of the API (from https://code.google.com/p/google-api-dotnet-client/wiki/APIs#Drive_API).
I changed line 122 in the Drive sample (instructions to download this sample are here), to
Title = "字/漢字" and Title = "title with ç", and both of them worked for me.

Related

Why can't StorageFile.GetFileFromPathAsync load from an exsisting PDF file

I am trying to pass a PDF generated from a SQL ReportServer back to a UWP application as a PdfDocument. I keep getting an Exception when trying to create the StorageFile
[HttpGet]
[Route("invoicereport/{report}/{invoice}")]
public async Task<IHttpActionResult> GetInvoiceReport([FromUri] string report, [FromUri] string invoice)
{
try
{
Debug.WriteLine("Test");
ReportExecutionService rs = new ReportExecutionService();
rs.Credentials = CredentialCache.DefaultCredentials;
rs.Url = "http://localhost/reportserver/reportexecution2005.asmx";
rs.ExecutionHeaderValue = new ExecutionHeader();
var executionInfo = new ExecutionInfo();
executionInfo = rs.LoadReport($"{ReportsDir}/Invoice/{report}", null);
List<ParameterValue> parameters = new List<ParameterValue>();
parameters.Add(new ParameterValue { Name = "SOPNUMBER", Value = invoice });
parameters.Add(new ParameterValue { Name = "SOPTypeString", Value = "Invoice" });
rs.SetExecutionParameters(parameters.ToArray(), "en-US");
string deviceInfo = "<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
string mimeType;
string encoding;
string[] streamId;
Warning[] warning;
var result = rs.Render("PDF", deviceInfo, out mimeType, out encoding, out encoding, out warning, out streamId);
FileStream stream = File.Create(System.Web.HttpRuntime.CodegenDir + $"/{invoice}.pdf", result.Length);
//write file with rendered result
stream.Write(result, 0, result.Length);
//close stream
stream.Close();
StorageFile file = StorageFile.GetFileFromPathAsync(System.Web.HttpRuntime.CodegenDir + $"/{invoice}.pdf").GetResults();
var pdf = PdfDocument.LoadFromFileAsync(file).GetResults();
return Ok(pdf);
}
catch (Exception ex)
{
Log.Logger.Error(ex, "Reporting Error");
}
return Ok();
}
the Exception gets logged as:
System.IO.FileNotFoundException: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
at Windows.Foundation.IAsyncOperation`1.GetResults()
at Prism.Web.Queries.Controllers.ReportController.<GetInvoiceReport>d__6.MoveNext() in C:\Projects\PointOfSaleBeta\Prism.Web.Queries\Controllers\ReportController.cs:line 183
Line 183 corresponds to StorageFile file = StorageFile.GetFileFromPathAsync(System.Web.HttpRuntime.CodegenDir + $"/{invoice}.pdf").GetResults();
I have verified (many times) that the referenced PDF file actually got created. Am I not using the correct syntax for 'GetFileFromPathAsync`?
After I didn't get any answers or comments I tried a different approach. I installed the FreeSpire.PDF nuget package:
[HttpGet]
[Route("invoicereport/{report}/{invoice}")]
public async Task<IHttpActionResult> GetInvoiceReport([FromUri] string report, [FromUri] string invoice)
{
try
{
Debug.WriteLine("Test");
ReportExecutionService rs = new ReportExecutionService();
rs.Credentials = CredentialCache.DefaultCredentials;
rs.Url = "http://localhost/reportserver/reportexecution2005.asmx";
rs.ExecutionHeaderValue = new ExecutionHeader();
var executionInfo = new ExecutionInfo();
executionInfo = rs.LoadReport($"{ReportsDir}/Invoice/{report}", null);
List<ParameterValue> parameters = new List<ParameterValue>();
parameters.Add(new ParameterValue { Name = "SOPNUMBER", Value = invoice });
parameters.Add(new ParameterValue { Name = "SOPTypeString", Value = "Invoice" });
rs.SetExecutionParameters(parameters.ToArray(), "en-US");
string deviceInfo = "<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
string mimeType;
string encoding;
string[] streamId;
Warning[] warning;
var result = rs.Render("PDF", deviceInfo, out mimeType, out encoding, out encoding, out warning, out streamId);
PdfDocument pdf = new PdfDocument();
pdf.LoadFromBytes(result);
return Ok(pdf);
}
catch (Exception ex)
{
Log.Logger.Error(ex, "Reporting Error");
}
return Ok();
}
This solved (worked around) my problem.

ASP.Net returning corrupted byte array to my application via WebClient

I have an asp.net application(locally for testing) setup along with an FTP server with a file on it. I am trying to have my .exe get a byte array that my asp.net application gets from my FPT server. This works when I get the data directly from my FTP server from my .exe, the data from the file its download is correct. I tested this by getting the length. When I go return a the size of the byte array as a string from the asp.net application .exe->asp.net->ftp->asp.net->.exe the length of the byte array is 7. but if i go directly from the .exe to the ftp server .exe->ftp->.exe the length of the byte array is 47616 which is correct for the size of the file. Now the part that confuses me, if I go .exe->asp.net->ftp->asp.net->.exe by having the asp.net application return the byte array it downloaded from the ftp server to the .exe, if I get the length of the returned byte array it has a length of 63490. The file size is 46.5KB. Im just completely lost here, any insight would be wonderful, thank you!
edit: added more asp.net and .exe code.
more details: When I call mainFunction(which is c++ in a separate .dll) it will fail on the commented line below with the .dll data from the asp.net application since it acts like its not a valid .dll(i can assure you the .dll functions properly as intended. everything works properly until i tried to get the asp.net application to get the file data for me instead of it being in the .exe(which works as intended just fine). Ive also never used asp.net before this or even really looked into the use, but i do not really need it for any other purpose aside from downloading the .dll data and returning it to the .exe.
c++ .dll portion
bool ManualMap(HANDLE hProc, BYTE fileData[])
{
BYTE * pSrcData = nullptr;
IMAGE_NT_HEADERS * pOldNtHeader = nullptr;
IMAGE_OPTIONAL_HEADER * pOldOptHeader = nullptr;
IMAGE_FILE_HEADER * pOldFileHeader = nullptr;
BYTE * pTargetBase = nullptr;
std::ifstream File("C:", std::ios::binary | std::ios::ate);
auto FileSize = 53760;
pSrcData = new BYTE[static_cast<UINT_PTR>(FileSize)];
if (!pSrcData)
{
MessageBox(NULL, "Memory allocating failed", NULL, NULL);
return false;
}
pSrcData = fileData;
reinterpret_cast<char*>(pSrcData);
if (reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_magic != 0x5A4D) //here
{
MessageBox(NULL, "Invalid File", NULL, NULL);
delete[] pSrcData;
return false;
}
asp.net
public byte[] Get(string id)
{
WebClient WC = new WebClient();
string FileName = "file.dll";
string FTPURL = "ftp://address/";
string Username = "username";
string Password = "password";
string CompletePath = FTPURL + FileName;
try
{
WC.Credentials = new NetworkCredential(Username, Password);
return WC.DownloadData(new Uri(CompletePath));
}
catch (Exception e)
{
return new byte[0];
}
}
.exe
private bool InjectFile(byte[] Data)
{
return mainFunction(Data, "app.exe");
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
byte[] Data = WC.DownloadData(URL + "1");
if (Data.Length > 0)
{
if (InjectFile(Data))
MessageBox.Show("Injection Successful");
else
MessageBox.Show("Injection Failed");
}
else
MessageBox.Show("Error retreiving file data from server");
}
Update ASP.NET action to return a file
public ActionResult Get(string id)
{
WebClient WC = new WebClient();
string FileName = "file.dll";
string FTPURL = "ftp://address/";
string Username = "username";
string Password = "password";
string CompletePath = FTPURL + FileName;
try
{
WC.Credentials = new NetworkCredential(Username, Password);
return File(WC.DownloadData(new Uri(CompletePath)), "application/octet-stream");
}
catch (Exception e)
{
return File(new byte[0], "application/octet-stream");
}
}

How to upload image on amzon s3 using .net web api c#?

I have create one api for the image upload. in this code i have upload time image download in my local folder and store. but i need now change my code and move this image download on amzon s3. i have found one link in searching time but in this link static image is upload i need image browse from the file upload control and download on amzon server. but how can do that i have no idea. please any one how can do that then please help me. here below listed my code. and also add i have try this code in below.
this is my api method for the image upload :
[HttpPost]
[Route("FileUpload")]
public HttpResponseMessage FileUpload(string FileUploadType)
{
try
{
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
string fname = System.IO.Path.GetFileNameWithoutExtension(postedFile.FileName.ToString());
string extension = Path.GetExtension(postedFile.FileName);
Image img = null;
string newFileName = "";
newFileName = DateTime.Now.ToString("yyyyMMddhhmmssfff") + ".jpeg";
string path = ConfigurationManager.AppSettings["ImageUploadPath"].ToString();
string filePath = Path.Combine(path, newFileName);
SaveJpg(img, filePath);
return Request.CreateResponse(HttpStatusCode.OK, "Ok");
}
}
}
catch (Exception ex)
{
return ex;
}
return Request.CreateResponse(HttpStatusCode.OK, "Ok");
}
This is my save image api =>
public static void SaveJpg(Image image, string file_name, long compression = 60)
{
try
{
EncoderParameters encoder_params = new EncoderParameters(1);
encoder_params.Param[0] = new EncoderParameter(
System.Drawing.Imaging.Encoder.Quality, compression);
ImageCodecInfo image_codec_info =
GetEncoderInfo("image/jpeg");
image.Save(file_name, image_codec_info, encoder_params);
}
catch (Exception ex)
{
}
}
i have try this code with static image upload on server =>
private string bucketName = "Xyz";
private string keyName = "abc.jpeg";
private string filePath = "C:\\Users\\I BALL\\Desktop\\image\\abc.jpeg";. // this image is store on server
public void UploadFile()
{
var client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1);
try
{
PutObjectRequest putRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = keyName,
FilePath = filePath,
ContentType = "text/plain"
};
PutObjectResponse response = client.PutObject(putRequest);
}
catch (AmazonS3Exception amazonS3Exception)
{
if (amazonS3Exception.ErrorCode != null &&
(amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId")
||
amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
{
throw new Exception("Check the provided AWS Credentials.");
}
else
{
throw new Exception("Error occurred: " + amazonS3Exception.Message);
}
}
}
here i have show my code but i need to marge with my code so how can do that please any one know how can do that.
This might be too late, but here is how I did it:
Short Answer: Amazon S3 SDK for .Net has a class called "TransferUtility" which accepts a Stream object, so as long as you can convert your file to any Class derived from the abstract Stream class, you can upload the file.
Long Answer:
The httprequest posted files has an inputStream property, so inside your foreach loop:
var postedFile = httpRequest.Files[file];
If you expand on this object, it is of type "HttpPostedFile", so you have access to the Stream through the InputStream property:
Here is some snippets from a working sample:
//get values from the headers
HttpPostedFile postedFile = httpRequest.Files["File"];
//convert the posted file stream a to memory stream
System.IO.MemoryStream target = new System.IO.MemoryStream();
postedFile.InputStream.CopyTo(target);
//the following static function is a function I built which accepts the amazon file key and also the object that will be uploaded to S3, in this case, a MemoryStream object
s3.WritingAnObject(fileKey, target);
The S3 is an instance of a class called "S3Uploader", here are some snippets that can get you going,
below are some needed namespaces:
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
class constructor:
static IAmazonS3 client;
static TransferUtility fileTransferUtility;
public S3Uploader(string accessKeyId, string secretAccessKey,string bucketName)
{
_bucketName = bucketName;
var credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey);
client = new AmazonS3Client(credentials, RegionEndpoint.USEast1);
fileTransferUtility = new TransferUtility(client);
}
Notice here that we are creating the credentials using the BasicAWSCredentials class instead of passing it to the AmazonS3Client directly. And then we are using fileTransferUtility class to have better control over what is sent to S3. and here is how the Upload works based on Memory Stream:
public void WritingAnObject(string keyName, MemoryStream fileToUpload)
{
try
{
TransferUtilityUploadRequest fileTransferUtilityRequest = new
TransferUtilityUploadRequest
{
StorageClass = S3StorageClass.ReducedRedundancy,
CannedACL = S3CannedACL.Private
};
fileTransferUtility.Upload(fileToUpload, _bucketName, keyName);
}
catch (AmazonS3Exception amazonS3Exception)
{
//your error handling here
}
}
Hope this helps someone with similar issues.

Upload an image to Google Drive with OCR and convert to Doc

I want to upload an image to Google Drive with OCR function and convert it to Google Doc. I am using this method
public static File UploadFile(DriveService Service, string UploadFile, string Parent)
{
if (System.IO.File.Exists(UploadFile))
{
File body = new File();
body.Title = System.IO.Path.GetFileName(UploadFile);
body.Description = "File uploaded by Diamto Drive Sample";
body.MimeType = GetMimeType(UploadFile);
body.Parents = new List<ParentReference>() { new ParentReference() { Id = Parent } };
// File’s content.
byte[] byteArray = System.IO.File.ReadAllBytes(UploadFile);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
try
{
FilesResource.InsertMediaUpload request = Service.Files.Insert(body, stream, GetMimeType(UploadFile));
request.Ocr = true;
request.OcrLanguage = "he";
request.Convert = true;
return request.ResponseBody;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
return null;
}
}
else
{
Console.WriteLine("File does not exist: " + UploadFile);
return null;
}
}
and I call it via this line
Google.Apis.Drive.v2.Data.File newFile = DriveHelper.UploadFile(service, #"E:\myImage.png", myFolderId);
My problem is: request.ResponseBody returns null but when I remove this lines
request.Ocr = true;
request.OcrLanguage = "he";
request.Convert = true;
My file uploaded successfully
and request.ResponseBody returns File Object
This is missing the Upload function.
request.Upload();
return request.ResponseBody;
Reference link: http://anthonygiretti.com/category/google-api/

File upload in asp.net c#

hey guys, m using an api of "Bits on the Run" following is the code of upload API
public string Upload(string uploadUrl, NameValueCollection args, string filePath)
{
_queryString = args; //no required args
WebClient client = createWebClient();
_queryString["api_format"] = APIFormat ?? "xml"; //xml if not specified - normally set in required args routine
queryStringToArgs();
string callUrl = _apiURL + uploadUrl + "?" + _args;
callUrl = uploadUrl + "?" + _args;
try {
byte[] response = client.UploadFile(callUrl, filePath);
return Encoding.UTF8.GetString(response);
} catch {
return "";
}
}
and below is my code to upload a file, m using FileUpload control to get the full path of a file(but m not succeeded in that)...
botr = new BotR.API.BotRAPI("key", "secret_code");
var response = doc.Descendants("link").FirstOrDefault();
string url = string.Format("{0}://{1}{2}", response.Element("protocol").Value, response.Element("address").Value, response.Element("path").Value);
//here i want fullpath of the file, how can i achieve that here
string filePath = fileUpload.PostedFile.FileName;//"C://Documents and Settings//rkrishna//My Documents//Visual Studio 2008//Projects//BitsOnTheRun//BitsOnTheRun//rough_test.mp4";
col = new NameValueCollection();
FileStream fs = new FileStream(filePath, FileMode.Open);
col["file_size"] = fs.Length.ToString();
col["file_md5"] = BitConverter.ToString(HashAlgorithm.Create("MD5").ComputeHash(fs)).Replace("-", "").ToLower();
col["key"] = response.Element("query").Element("key").Value;
col["token"] = response.Element("query").Element("token").Value;
fs.Dispose();
string uploadResponse = botr.Upload(url, col, filePath);
i read in some forums saying that for some security purpose you can't get fullpath of a file from client side. If it is true then how can i achieve file upload in my scenario ?
Yes, this is true, for security reason you cannot get the fullpath of the client machine, what you can do is, try the following,
Stream stream = fileUpload.PostedFile.InputStream;
stream.Read(bytes, 0, fileUpload.PostedFile.ContentLength);
instead of creating your own FileStream use the stream provided by the FileUploadControl. Hoep it shall help.

Categories