I have been trying to implement file upload to BrickFTP using Dropzone, but the uploaded file won't open because it contains the WebKitFormBoundary at the top of the file content.
I'm putting method as PUT in Dropzone configuration as per BrickFTP's documentation. BrickFTP uses Amazon S3 so the files are actually being uploaded to S3. I did everything as per their documentation, and everything worked except this last problem I'm having with those extra information at the top of the uploaded file content.
Here is the Coffeescript code responsible for file upload:
brickFTPData = {}
# As per BrickFTP docs, step 1 is
# to get the dedicated upload url for each file by sending a
# request to REST API to indicate intent to upload a file
getUploadUri = (file) ->
result = ""
$.ajax
url : '/a/portal-dev/get-api-keys'
type : 'POST'
dataType : 'json'
data : { file_name: file.name }
async : false
success : (data, textStatus, jqXHR) ->
brickFTPData[file.upload.uuid] =
file_name : file.name
upload_uri : data.upload_uri
ref : data.ref
result = data.upload_uri
return result
# 3rd step is to notify the REST API that the file upload is complete.
finishUpload = (file) ->
$.ajax
url : '/a/portal-dev/upload-done'
type : 'POST'
dataType : 'json'
data :
ref : brickFTPData[file.upload.uuid].ref
file_name : brickFTPData[file.upload.uuid].file_name
success : (data) ->
delete brickFTPData[file.upload.uuid]
console.log data.status
# 2nd step is to upload the file
sampleQuoteDropzone = new Dropzone "#sampleQuoteDropzone",
url : '/demo'
method : 'PUT'
headers : {"Content-Type": "application/octet-stream"}
success : (file, request) ->
finishUpload(file)
sampleQuoteDropzone.on 'processing', (file) ->
upload_uri = getUploadUri(file)
sampleQuoteDropzone.options.url = upload_uri
Upload works fine using the above code but as said when I open the uploaded file into a text editor it starts with following code:
------WebKitFormBoundaryw4bIakMBbkp7ES2E
Content-Disposition: form-data; name="file"; filename="IMG_5652.jpg"
Content-Type: image/jpeg
If I delete these lines and save the file it will work.
But this problem is not seen when uploading file using a regular ajax call outside Dropzone. Following is the working code:
$.ajax
url: data.upload_uri
type: 'PUT'
contentType: 'application/octet-stream'
data: file
processData: false
success: (response) ->
finishUpload(file, data)
Can anyone please advise how to solve this problem?
I solved the problem with following code:
sampleQuoteDropzone.on 'sending', (data, xhr, formData) ->
_send = xhr.send
xhr.send = ->
_send.call(xhr, data)
This solution was actually found here. I saw this before posting this question here, but wasn't sure if this is the right problem/solution. I contacted BrickFTP and they responded fairly quickly saying this solution may work for me, and yes it certainly does.
Related
To be brief with the requirement:
My folder structure looks as below:
Requirement & Challenge: When I try to read the FixedTestFile.dat
from different features, the read method appends the path wrong followed by the path of feature file and hence fails.
Tried with the following ways to read the file but failed with error.
And multipart file myFile = { read: 'src/test/java/e2e/common/data/FixedTestFile.dat', filename: #(randomFileName), contentType: 'text/plain' }
Logs:
Requirement: I have to read file "FixedTestFile.dat" from different features located in folders individual and testScenarios while using in Mutlipart file myFile.
Note : I tried with using classpath: and file: But no luck
And multipart file myFile = { read: 'classpath:e2e/common/data/FixedTestFile.dat', filename: #(randomFileName), contentType: 'text/plain' }
Tried using a variable for filename with path and tried using this as a parameter in read. Did not work.
* string myDataFileWithPath = "\'"+"../common/data/"+fileName+".dat"+"\'"
And multipart file myFile = { read: myDataFileWithPath, filename: #(randomFileName), contentType: 'text/plain' }
So the question is: "How to read a file from two features in another location?" Precisely for a multipart file upload.
Am I missing something or it is a bug while reading files?
I would like to upload multiple image files in one request using multipart. I have reviewed the Karate examples on this, but the multiple file upload does not meet my need (/multiple endpoint here - https://github.com/intuit/karate/blob/master/karate-demo/src/main/java/com/intuit/karate/demo/controller/UploadController.java). My service method (Spring REST) signature expects an array of MultipartFile[] so that I can accept any number of files. Here is my scenario:
Scenario: Upload multiple files
* def json = {}
* set json.files[0] = { read: 'file1.jpg', filename: 'file1.jpg', contentType: 'image/jpeg' }
* set json.files[1] = { read: 'file2.jpg', filename: 'file2.jpg', contentType: 'image/jpeg' }
Given path '/rest'
And multipart files json
When method post
Then status 200
And here is the Spring web service method (just trying to receive the files right now, so the method doesn't do much):
#PostMapping("/rest")
public String handleFileUpload(#RequestParam("file") MultipartFile[] file) {
System.out.println("Len: " + file.length);
for(MultipartFile currentFile : file) {
System.out.println("In here: " + currentFile.getOriginalFilename());
}
return file[0].getOriginalFilename();
}
When I run this I receive a Karate error: 'multipart file value should be json'
If I change the scenario to do this:
Scenario: Upload multiple files
* def json = {}
* set json.files = { read: 'file1.jpg', filename: 'file1.jpg', contentType: 'image/jpeg' }, { read: 'file2.jpg', filename: 'file2.jpg', contentType: 'image/jpeg' }
Given path '/rest'
And multipart files json
When method post
Then status 200
Then the test executes ok, but only one file ends up in the MultipartFile array 'files' (service method argument).
What is the proper way to upload multiple files to the web service method above using Karate?
Edit: Adding client code (below) and updated Spring method above.
Here is a simple HTML form that will submit multiple files to the Spring method above:
<form method="POST" enctype="multipart/form-data" action="/rest">
<table>
<tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr>
<tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr>
<tr><td></td><td><input type="submit" value="Upload" /></td></tr>
</table>
</form>
When submitted I get 2 files in the service method.
Seems that it does work, you just need to send the same parameter twice in the feature file
And multipart file files = { read: 'mergeTest.pdf', filename: 'upload-name.pdf', contentType: 'application/pdf' }
And multipart file files = { read: 'mergeTest.pdf', filename: 'upload-name.pdf', contentType: 'application/pdf' }
And multipart field filesMetadata = .........................................
my service:
public ResponseEntity<StreamingResponseBody> mergePdfs(#RequestPart #Validated
List<FileMetaData> filesMetadata, #RequestPart #Validated List<MultipartFile> files)
Wow, never seen this before and it is likely that Karate does not support it. I'm also wondering if this is legal as per the HTTP spec - as far as I know - each file has to have unique field-name. Do you have the corresponding client-side code for the Apache HTTP Client, that would help.
EDIT: also see answer by Esteban Lopez below: https://stackoverflow.com/a/59833358/143475
Your best bet may be to submit a feature request and also contribute code to expedite. Note that this is the first time in 2 years that anyone has reported this as a problem.
I created an API function to work with S3. I imported the template swagger. After deployment, I tested with a Node.js project by the npm module aws-api-gateway-client.
It works well with: get bucket lists, get bucket info, get one item, put a bucket, put a plain text object, however I am blocked with put a binary file.
firstly, I ensure ACL is allowed with all permissions on S3. secondly, binary support also added
image/gif
application/octet-stream
The code snippet is as below. The behaviors are:
1) after invokeAPI, the callback function is never hit, after sometime, the Node.js project did not respond. no any error message. The file size (such as an image) is very small.
2) with only two times, the uploading seemed to work, but the result file size is bigger (around 2M bigger) than the original file, so the file is corrupt.
Could you help me out? Thank you!
var filepathname = './items/';
var filename = 'image1.png';
fs.stat(filepathname+filename, function (err, stats) {
var fileSize = stats.size ;
fs.readFile(filepathname+filename,'binary',function(err,data){
var len = data.length;
console.log('file len' + len);
var pathTemplate = '/my-test-bucket/' +filename ;
var method = 'PUT';
var params = {
folder: '',
item:''
};
var additionalParams = {
headers: {
'Content-Type': 'application/octet-stream',
//'Content-Type': 'image/gif',
'Content-Length': len
}
};
var result1 = apigClient.invokeApi(params,pathTemplate,method,additionalParams,data)
.then(function(result){
//never hit :(
console.log(result);
}).catch( function(result){
//never hit :(
console.log(result);
});;
});
});
We encountered the same problem. API Gateway is meant for limited data (10MB as of now), limits shown here,
http://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html
Self Signed URL to S3:
Create an S3 self signed URL for POST from the lambda or the endpoint where you are trying to post.
How do I put object to amazon s3 using presigned url?
Now POST the image directly to S3.
Presigned POST:
Apart from posting the image if you want to post additional properties, you can post it in multi-form format as well.
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createPresignedPost-property
If you want to process the file after delivering to S3, you can create a trigger from S3 upon creation and process with your Lambda or anypoint that need to process.
Hope it helps.
I would like to upload a xml file from the local workspace and use it as model. I can upload files to the server but i don't know how to retrieve the data from the uploaded object and set or load it to my model
Here is how I m uploading the file.
jQuery.ajax({
url: oFileUploader.getUploadUrl(),
headers: oHeaders,
type: 'PUT',
cache: false,
contentType: false,
processData: false,
data: file
});
}
I could not use the standard oFileUploader.upload() because it uses the http method "POST" and I wanted to do a "PUT"
Thank you
It is not clear how you get the contents of the file variable that you are passing to the jQuery.ajax call. Depending on this, you have three options hat come to mind:
Directly use the file variable contents in a model.
Use the FileReader API to read the file contents and put them in a model.
Make the back-end service return the XML content of the file as a response to the AJAX call and then store the response in a model.
Does anyone have an example of uploading a file to the server using ringojs?
There's a simple upload example in the demo app, but it stores uploads in-memory which is not a good idea for most apps. To save uploads to a temporary file you'll currently have to do something like this (this is a modified version of the upload demo action):
var fu = require("ringo/webapp/fileupload");
function upload(req) {
if (fu.isFileUpload(req.contentType)) {
var params = {};
fu.parseFileUpload(req, params, req.charset, fu.TempFileFactory);
return {
status: 200,
headers: {"Content-Type": "text/plain"},
body: [params.file.name, " saved to ", params.file.tempfile]
};
}
return Response.skin(module.resolve('skins/upload.txt'), {
title: "File Upload"
});
}
Unfortunately, there was a bug with saving uploads to temp files that I just fixed, so you'll have to use a current git snapshot or patch file modules/ringo/webapp/fileupload.js manually:
http://github.com/ringo/ringojs/commit/1793a815a9ca3ffde4aa5a07c656456969b504f9
We also need some high level way of doing this for the next release (e.g. setting a req.uploadTempDir property). I'll open an issue for this.