I was writing end to end test case for a site. In this site, user is supposed to upload python file. I want to test what happens if I rename png file with `.py extension and upload it. When I did manually, the website gave the error
ERROR: You have submitted a file factorial.py of type py but the contents are of image/png type
However, when I uploaded through cypress using cypress-file-upload plugin, it gave me following error:
ERROR: You have submitted a file factorial.py of type py but the contents are of application/octet-stream type
Why is this so? Am I missing something or am getting diffrent message because of the way the plugin uploads file in some peculiar manner? Can I imitate the manual file upload output through cypress (that is get exactly the same error of image/png type)?
Update
I also checked for the mp3 file. Manual upload was giving error:
ERROR: You have submitted a file factorial.py of type py but the contents are of audio/mpeg type
whereas cypress upload was giving same application/octet-stream type-error.
Also, my code to upload the file looks like this:
cy.get('input[name="docfile"]').attachFile(filePath)
cy.contains('input','Upload').click()
Explicitly adding a mimetype also doesn't work and still gives same error:
cy.get('input[name="docfile"]').attachFile({ filePath: _filePath, mimeType : _mimeType })
Related
I have an XLSM (macro enabled with sheet level formatting) file in my repository. I have used 'xlsx-populate' node library to read the file, add rows and save it in the repository successfully. I pass the work book to front end, setting the headers and MIME type for XLSM file, the file gets downloaded but upon trying to open it says 'Excel cannot open the file because the file format is not valid. Verify that the file has not been corrupted and that the extension matches the format of the file'. The same flow is successfully working for an XLSX file though. Is it possible that angular supports XLSM file download (possibly) with any alternative library? Is it the way in which the content is being sent that needs alteration? I am also open to any alternative approaches/suggestions.
MIME type for XLSM: application/vnd.ms-excel.sheet.macroEnabled.12
Code snippet:
this.content = XlsxPopulate.fromFileAsync(__dirname + "myFile.xlsm");
downloadFile(req,res) {
res.setHeader('Content-Type', xlsmMimeType);
res.setHeader('Content-Disposition', 'attachment; filename=myFileName');
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
res.send(this.content)
}
The HTTP headers (Content-Type) and the metadata that an HTML file input returns (file.type) are not reliable and could be easily bypassed by hackers. So how do you make sure that the file that is going to be uploaded to S3 has the correct file type when using AWS s3 presigned[-post]-urls?
There are packages like file-type that can detect the actual type of a file. But the problem is that in order to detect the file type they need the content of the file as a buffer or Uint8Array. So I have to send the file twice. Once to the server to detect the file type and the presigned-url (if it has a correct type), and once for actually uploading it to s3, which is obviously a bad thing.
I have a mobile app that wraps around the web-app, using webview.
The web-app has a button to open a large .zip file (e.g. 100 MB).
The user clicks a button, and selects a .zip file.
This triggers an onChange function with a variable of type File (Blob), which includes attributes like:
file name
file size
file type (application/zip)
The javascript code then parses the .zip file, extracts specific data within it and uses it within the web-app.
This works well within the web-app, when the app is called via the Chrome browser.
For example when operated in chrome browser on an Android phone, I can pull the .zip file and open it in the web-app.
I want to do the same but using the mobile app.
I am able to pick up the .zip file using a File Chooser, and pass it to Webview but I have problems to fetch the file from the Javascript code.
For reference, I am able to pass an image, by creating a data_uri using stringBuilder and passing the content (as data:image/jpeg;base64).
But the zip file is much larger.
When calling fetch(fileUri) from the Javascript side I'm getting errors.
I'm using the following uri
/storage/emulated/0/Android/data/com.example/files/Download/file2.zip
The fetch succeeds but returns a blob with size of 165 (i.e. not the actual size of the file) which hosts the error message:
{
"error": "Not Found",
"message": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."
}
The program flow is like so:
I select a .zip file via FileChooser.
In onActivityResult, the uri value is /document/msf:12858 (seen via uri = intent.getData();)
The uri needs to be mapped into a real path file url, such that the fileUrl will be passed to webview.
Webview will then fetch the file using the fileUrl.
I searched how to get the real path file url when selecting a file with FileChooser, and found
this, and this links.
I wasn't able to get the real file path, so I decided to read the file and write it to another location, so I can get a file path. (this is not efficient and done just to check the functionality).
I create the new file using the following code:
InputStream stream = context.getContentResolver().openInputStream(uri);
File file2 = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "file2.zip");
writeBytesToFile(stream, file2);
I don't see any errors when creating the file, and when creating the file, the number of bytes that are read and written to the new file are as expected.
For file2, I get a value of:
/storage/emulated/0/Android/data/com.example/files/Download/file2.zip
Then, within the Javascript code I fetch this file path.
But I'm getting a Blob with the "file-not-found" content as above.
So:
How can I verify that the file is indeed created and that the path can be fetched from webview?
How can I get the real file path of the original selected file, so I don't have to read and write the original file to new location just to get the file path?
Thanks
I was able to get the file from external storage by doing the following steps:
create an initial uri (uri1)
The uri is created by:
creating a temporary file (file1) in the storage dir via
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
I'm not sure why a temporary file need to be created but if I don't create a file I cannot get the uri.
createFile3
get the uri via
Uri uri1 = FileProvider.getUriForFile(context, "com.example.android.fileprovider", file1);
create an intent with the following attributes:
Intent.ACTION_OPEN_DOCUMENT
category: Intent.CATEGORY_OPENABLE
type: "application/zip"
extra attribute: fileIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri1);
this opens a dialog box for selecting openable zip files in the Downloads directory,
after the file is selected, a new uri (uri2) is created that includes the name of the selected file.
extract the name of the file via
String fileName = getFileName(context, uri2);
create the dirPath by appending the filename
dirPath = "/data/user/0/com.example/" + fileName;
if the dirPath does not exist (first time), write the file to its dirPath location.
on successive ocassions dirPath exists, so there is no need to re-write the file.
open the file with regular Java means, e.g. via
ZipFile zip = new ZipFile(dirPath);
I'm trying to modify the project so I could plug in a file path or a file as a variable instead of the user choosing the model file. So I'm looking for where the actual upload happens.
In submitProject():
https://github.com/cyrillef/extract.autodesk.io/blob/master/www/js/app.js#L129
I see that it just sends (with an ajax request) an object that holds the file name and unique identifier but not the actual binary file.
In here:
https://github.com/cyrillef/extract.autodesk.io/blob/master/www/js/upload-flow.js#L34
there's r.upload(), is this the actual upload of the model?
Does it start to upload the file right as you press ok in the file chooser?
Is there a way to give it a file path to upload instead of uploading with the form and file chooser?
The author of this sample should be on Christmas vacation, I just downloaded and setup the extractor sample on my machine, with a little debug into the code, let me try to answer as much as I can.
In general, I think some of your understanding is correct, but let me explain a little more:
For a local file to be uploaded and translated, there are actually 2 steps of actual “upload”.
As you mentioned, when you press ok in the file chooser, yes, the file will be first uploaded to the "extractor" server as you noticed by some methods like r.upload(), it’s actually using a JavaScript library call “flow.js", which provides multiple simultaneous, stable, fault-tolerant and resumable/restartable file uploads via the HTML5 File API. I am not expert on this, but you can check that module about how to use it to upload a file.
By now, your file is uploaded from client to the "extractor" server, but if you want to translate the file to "svf", the file is required to be uploaded to Autodesk Server(OSS), that is done by clicking “submit my project” buton, when you click this button, as you mentioned, from client, it will call the method submitProject() in https://github.com/cyrillef/extract.autodesk.io/blob/master/www/js/app.js, this method will send a post request of “/api/projects” to the "extractor" server, if you check the code at server side https://github.com/cyrillef/extract.autodesk.io/blob/master/server/projects.js , you can see the extractor server actually upload the file to Autodesk OSS, and then triggers the translation service.
This feature (passing a URL string vs a file binary) is already implemented. You can use the uri: edit box and paste your file URL there. It supports http(s) or S3 uri with access token.
The physical upload happens in this file, whereas the SubmitProject() code sends only information as JSON. The JSON object only contains a reference to the file which was uploaded using flow.js. But would contain the uri string if you had choose that method.
I want to prevent people from, say, uploading a movie file or shell script by just adding a jpg extension to my avatar upload endpoint. I haven't written the backend to upload script in a long time but I remember PHP being able to tell me the actual file type, not just the type based on the file extension. I can also check this purely on the front-end JS. Or in Java there's http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#probeContentType%28java.nio.file.Path%29
The issue is in vanilla Node and using a bunch of mime related modules including mmmagic are just returning the mime type based on the file extension. For example, I removed the gif extension on a gif file and changed it to txt and both Node and mmmagic just return text/plain.
In Java, I was using Tika, which is a mime type detector tool. Turns out, there is nodejs bridge for it, node-tika.
To use
npm install node-tika
and
var tika = require('tika');
tika.type('test/data/file.pdf', function(err, contentType) {
console.log(contentType); // Logs 'application/pdf'.
});