I have a pdf which has rupee symbol(₹) in it. I am using aws-sdk with nodejs to upload the pdf to s3.
Rupee symbol is missing after uploading to s3.
In local, while I upload, it is working fine. Where is eks, rupee symbol is missing in the pdf. Same behaviour is happening while i upload a file using apigateway to s3
Thank you
const content = fs.readFileSync(filePath);
const uploadToS3UsingSdk = async (bucket, key, content) => {
return new Promise((resolve, reject) => {
const awsConfig = {
accessKeyId: process.env.accessKeyId,
secretAccessKey: process.env.secretAccessKey,
region: process.env.region,
apiVersion: "2006-03-01",
};
const s3 = new AWS.S3(awsConfig);
const uploadParams = {
Bucket: bucket,
Key: key,
Body: content,
ContentType: "application/pdf;charset=utf-8",
};
s3.upload(uploadParams, function (err, data) {
if (err) {
console.log("Error", err);
return reject({
isSuccess: false,
errorMessage: err.errorMessage,
status: 500,
});
}
if (data) {
console.log("Upload Success", data.Location);
return resolve({
isSuccess: true,
errorMessage: null,
});
}
});
});
};
<!-- begin snippet: js hide: false console: true babel: false -->
PDF is not a wysiwyg (what you see is what you get) format.
Internally, it contains rendering instructions that tell a viewer (such as adobe reader) how to build the page.
Your document might contain something like:
Go to 80, 700
Set the active font to F1, font size 12
Set the drawing color to 0,0,0 in RGB mode
Render the glyph at index 251 of the active font
A PDF will also contain a so called resource dictionary, which clarifies which font F1 is.
This is where it might go wrong.
Standard 14 Fonts
The PDF specification (ISO32000) defines a handful of fonts as special (standard type 1 fonts). These fonts should always be present in the reader.
They include:
Helvetica
Helvetica Bold
Helvetica Bold Italic
Helvetica Italic
ZapfDingBats (symbols)
etc
When a piece of software builds a PDF it has 2 options:
Use one of the standard fonts
Insert the font in the PDF
If option 1 is selected, you are bound to those characters that are defined in the standard fonts. Not every font contains every character (for instance, none of the standard 14 contains chines characters)
If option 2 is selected, the font-file is embedded either in its entirety or partially in the PDF.
Subsetting
Partially embedded fonts are called subset fonts. This is a feature typically used when the font is large (contains a lot of characters) but the PDF doesn't use all those characters.
To put it simply, if the PDF only contains the text "Hello World", then there is no point in adding information on how to render the character "A".
Conclusion
These are possible things that might be wrong with your PDF:
You are using a standard font, which does not support the rupee symbol
You are using a custom font, that is not embedded. The reader will substitute this missing font (and the substitute font is typically a standard 14 font)
You are using a custom font, that is broken (not all PDF libraries do a good job of adhering to the standard). When a PDF is broken, a reader might decide to attempt to fix it. Fixes might include font-substitutions.
You are using a custom font, that does not have the rupee symbol.
You are using a custom (subset) font, whose subset does not include the rupee symbol.
There is an online tool to validate PDF documents. It's called VeraPDF.
You can find it here.
Related
I am using URQL as my react native graphql client. I like using the library but there doesn't seem to be an easy way to upload files selected from the expo image picker to my node server.
I did some googling, found a Ben Awad video where he uses ReactNativeFile to convert the result to a file. The issue is that this is the only way it seems fit for an apollo client. Is there something like this for urql? What would the code look like to convert the uri & base64 to a JS file?
...
if (!imageResult.cancelled) {
const file = new ReactNativeFile({
uri: imageResult.uri,
type: imageResult.type,
name: "picture"
});
image selection fn
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
base64: true,
aspect: [1, 1],
quality: 1,
});
if (result.cancelled || !result.uri || !onSuccessful) return;
await onSuccessful(result);
According to source code of the ReactNativeFile class (extract-files/public/ReactNativeFile.js) it just returns the same values you've entered. I don't see a problem to use plain object with same data. If you want to use this, you can, apollo-upload-client only exports ReactNativeFile from extract-files library (apollo-upload-client/public/ReactNativeFile.js)
Probably apollo-client checks if it is instanceof ReactNativeFile class but, I don't think URQL checks it.
You should follow the official URQL documentation for file uploads, and do not use apollo https://formidable.com/open-source/urql/docs/advanced/persistence-and-uploads/#file-uploads
I have to show image from USB device on my Linux based device.
My USB has a folder which has a non-ASCII character.
It is replaced by "?" character.
Original path : "file:///tmp/USB6/§§§§/Koala.jpg"
and
QML returns error : "QML Image: Cannot open: file:///tmp/USB6/????/Koala.jpg"
How will my Image be loaded with this path?
Image {
id: mainImage
source: iconRole
asynchronous: true
sourceSize.width: screenSize_Width
sourceSize.height: screenSize_Height
fillMode: Image.PreserveAspectCrop
onSourceChanged: {
console.log("SOURCE = ",source)
}
}
Logs I am getting : SOURCE = file:///tmp/USB6/§§§§/Koala.jpg
Error I am getting QML Image: Cannot open: file:///tmp/USB6/????/Koala.jpg.
Qt docs about URL:
Additionally, URLs may contain encoded characters using the
'percent-encoding' scheme specified by RFC 3986. These characters will
be preserved within properties of type url, to allow QML code to
construct precise URL values. An exception to this rule is the
preemptive decoding of directory-separator characters ('/') - these
characters are decoded to allow the URL to be correctly classified.
For example, a local file containing a '#' character, which would
normally be interpreted as the beginning of the URL 'fragment'
element, can be accessed by encoding the characters of the file name:
Image { source: encodeURIComponent("/tmp/test#1.png") }
This basic type is provided by the QML language.
It worked for this case.
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
Put this statement in main.cpp
We have a problem with MP4 video containing 5 languages captions embedded.
After transcoding in AWS transcoder, file contains no languages.
I want to keep original captions for languages and converting them into an other format (mov-text, cea-608 or cea-708)
The Job id : 1497397548070-s8ituv
Input Caption :
'InputCaptions': {
'MergePolicy': 'MergeRetain',
'CaptionSources' : []
}
Output Caption :
'Captions': {
'CaptionFormats': [{
'Format': 'cea-708'
}]
}
Is it because the captions of my input file is not in good format mov-text, CEA-608 or CEA-708?
Is it the good maneer to create the job for keep original captions and convert them?
Is it because of my preset (proprity of Audio or Video) ?
Can you help us ?
Best regard.
In summary
File.writeFile() creates a PNG file of 0 bytes when trying to write a Blob made from base64 data.
In my application, I am trying to create a file that consists of base64 data stored in the db. The rendered equivalent of the data is a small anti-aliased graph curve in black on a transparent background (never more that 300 x 320 pixels) that has previously been created and stored from a canvas element. I have independently verified that the stored base64 data is indeed correct by rendering it at one of various base64 encoders/decoders available online.
Output from "Ionic Info"
--------------------------------
Your system information:
Cordova CLI: 6.3.1
Gulp version: CLI version 3.9.1
Gulp local:
Ionic Framework Version: 2.0.0-rc.2
Ionic CLI Version: 2.1.1
Ionic App Lib Version: 2.1.1
Ionic App Scripts Version: 0.0.39
OS:
Node Version: v6.7.0
--------------------------------
The development platform is Windows 10, and I've been testing directly on a Samsung Galaxy S7 and S4 so far.
I know that the base64 data has to be converted into binary data (as a Blob) first, as File does not yet support writing base64 directly in to an image file. I found various techniques with which to do this, and the code which seems to suit my needs the most (and reflects a similar way I would have done it in java is illustrated below):
Main code from constructor:
this.platform.ready().then(() => {
this.graphDataService.getDataItem(this.job.id).then((data) =>{
console.log("getpic:");
let imgWithMeta = data.split(",")
// base64 data
let imgData = imgWithMeta[1].trim();
// content type
let imgType = imgWithMeta[0].trim().split(";")[0].split(":")[1];
console.log("imgData:",imgData);
console.log("imgMeta:",imgType);
console.log("aftergetpic:");
// this.fs is correctly set to cordova.file.externalDataDirectory
let folderpath = this.fs;
let filename = "dotd_test.png";
File.resolveLocalFilesystemUrl(this.fs).then( (dirEntry) => {
console.log("resolved dir with:", dirEntry);
this.savebase64AsImageFile(dirEntry.nativeURL,filename,imgData,imgType);
});
});
});
Helper to convert base64 to Blob:
// convert base64 to Blob
b64toBlob(b64Data, contentType, sliceSize) {
//console.log("data packet:",b64Data);
//console.log("content type:",contentType);
//console.log("slice size:",sliceSize);
let byteCharacters = atob(b64Data);
let byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
let slice = byteCharacters.slice(offset, offset + sliceSize);
let byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
let byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
console.log("size of bytearray before blobbing:", byteArrays.length);
console.log("blob content type:", contentType);
let blob = new Blob(byteArrays, {type: contentType});
// alternative way WITHOUT chunking the base64 data
// let blob = new Blob([atob(b64Data)], {type: contentType});
return blob;
}
save the image with File.writeFile()
// save the image with File.writeFile()
savebase64AsImageFile(folderpath,filename,content,contentType){
// Convert the base64 string in a Blob
let data:Blob = this.b64toBlob(content,contentType,512);
console.log("file location attempt is:",folderpath + filename);
File.writeFile(
folderpath,
filename,
data,
{replace: true}
).then(
_ => console.log("write complete")
).catch(
err => console.log("file create failed:",err);
);
}
I have tried dozens of different decoding techniques, but the effect is the same. However, if I hardcode simple text data into the writeFile() section, like so:
File.writeFile(
folderpath,
"test.txt",
"the quick brown fox jumps over the lazy dog",
{replace: true}
)
A text file IS created correctly in the expected location with the text string above in it.
However, I've noticed that whether the file is the 0 bytes PNG, or the working text file above, in both cases the ".then()" consequence clause of the File Promise never fires.
Additionally, I swapped the above method and used the Ionic 2 native Base64-To-Gallery library to create the images, which worked without a problem. However, having the images in the user's picture gallery or camera roll is not an option for me as I do not wish to risk a user's own pictures while marshalling / packing / transmitting / deleting the data-rendered images. The images should be created and managed as part of the app.
User marcus-robinson seems to have experienced a similar issue outlined here, but it was across all file types, and not just binary types as seems to be the case here. Also, the issue seems to have been closed:
https://github.com/driftyco/ionic/issues/5638
Anybody experiencing something similar, or possibly spot some error I might have caused? I've tried dozens of alternatives but none seem to work.
I had similar behaviour saving media files which worked perfectly on iOS. Nonetheless, I had the issue of 0 bytes file creation on some Android devices in release build (dev build works perfectly). After very long search, I followed the following solution
I moved the polyfills.js script tag to the top of the index.html in the ionic project before the cordova.js tag. This re-ordering somehow the issue is resolved.
So the order should look like:
<script src="build/polyfills.js"></script>
<script type="text/javascript" src="cordova.js"></script>
Works on ionic 3 and ionic 4.
The credits go to 1
I got that working with most of your code:
this.file.writeFile(this.file.cacheDirectory, "currentCached.jpeg", this.b64toBlob(src, "image/jpg", 512) ,{replace: true})
The only difference i had was:
let byteCharacters = atob(b64Data.replace(/^data:image\/(png|jpeg|jpg);base64,/, ''));
instead of your
let byteCharacters = atob(b64Data);
Note: I did not use other trimming etc. like those techniques you used in your constructor class.
I'm using fabric.js to dynamically create textures in Threes.js, and I need to save the textures to AWS. I'm using meteor-slingshot, which normally takes images passed in through a file selector input. Here's the uploader:
var uploader = new Slingshot.Upload("myFileUploads");
uploader.send(document.getElementById('input').files[0], function (error, downloadUrl) {
if (error) {
console.error('Error uploading', uploader.xhr.response);
alert (error);
}
else {
Meteor.users.update(Meteor.userId(), {$push: {"profile.files":downloadUrl}});
}
});
Uploading works fine from the drive ... but I'm generating my files in the browser, not getting them from the drive. Instead, they are generated from a canvas element with the following method:
generateTex: function(){
var canvTex = document.getElementById('texture-generator');
var canvImg = canvTex.toDataURL('image/jpeg');
var imageNew = document.createElement( 'img' );
imageNew.src = canvImg;
}
This works great as well. If I console.log the imageNew, I get my lovely image with base 64 encoding:
<img src="data:image/jpeg;base64,/9j/
4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgID
//....carries on to 15k or so characters
If I console.log a file object added from the drive via filepicker ( not generated from a canvas ), I can see what the file object should look like:
file{
lastModified: 1384216556000
lastModifiedDate: Mon Nov 11 2013 16:35:56 GMT-0800 (PST)
name: "filename.png"
size: 3034
type: "image/png"
webkitRelativePath: ""
__proto__: File
}
But I can't create a file from the blob for upload, because there is no place in the file object to add the actual data.
To sum up I can:
Generate an image blob and display it in a dom element
Upload files from the drive using meteor-slingshot
inspect the existing file object
But I don't know how to convert the blob into a named file, so I can pass it to the uploader.
I don't want to download the image, (there are answers for that), I want to upload it. There is a "chrome only" way to do this with the filesystem API but I need something cross browser (and eventually cross platform). If someone could help me with this, I would have uncontainable joy.
Slingshot supports blobs just as well as files: https://github.com/CulturalMe/meteor-slingshot/issues/22
So when you have a canvas object called canvTex and a Slingshot.Upload instance called uploader, then uploading the canvas image is as easy as:
canvTex.toBlob(function (blob) {
uploader.send(blob, function (error, downloadUrl) {
//...
});
});
Because blobs have no names, you must take that into account when defining your directive. Do not attempt to generate a key based on the name of the file.