Send multiple files to REST service via ICF handler class - web-services

I am creating an ICF handler class which reads file from application layer and I need to send the response back to sender with the files in the response. For this I am using MULTIPART format as below.
I am using ABAP as the programming language and we are on SAP_ABA 702 0010 version and do not have Gateway component yet.
server->response->set_header_field( name = 'Content-Type' value = 'multipart/form-data'). "#EC NOTEXT
lo_multipart = server->response->add_multipart( ).
filename = '/file1.jpg'.
CONCATENATE 'form-data; name="file"; filename="' filename '"' INTO lv_header_value.
lo_multipart->set_header_field( name = if_http_header_fields=>content_disposition
value = lv_header_value ).
server->response->set_data( data = attach_xstring ).
This works fine for 1 file which automatically downloads the file when browser is used. But I need to send 2 separate files in the body and to demarcate them with some information like file name, file extension and so on.
Could you please guide/help me on how to fix this ?

Related

Prevent Force Download of AWS S3 Files Django

I am using
storages.backends.s3boto3.S3Boto3Storage
storage backend to upload files in my django project.
field declaration in model:
document = models.FileField(upload_to=s3_directory_path.user_directory_path)
user_directory_path
def user_directory_path(instance, filename):
# TODO: Try to include this along with check filetype on the request object
document = instance.document
mime = magic.from_buffer(document.read(), mime=True)
extension = mimetypes.guess_extension(mime, strict=False)
file_name = str(uuid.uuid4()) + extension
document.seek(0)
return os.path.join("users", str(instance.user.id), file_name)
The saving of the document works perfectly fine, but the link which is generated force downloads the file. How can i avoid that?
Have a look at this answer to a general question about forcing file downloads via HTTP response headers. See also the MDN docs about Content-Disposition.
Can you show us the response headers you get when visiting the document URL?
It would be interesting to see how S3 delivers your files.
If you cannot change the headers in S3, you have the option to write a Django view that proxies the file download. Alternatively, configure your webserver (i.e. NGINX) to act as a proxy and set the required headers).
For Django, this section of the docs will show you how to set the headers.
response = HttpResponse(
document,
headers={
'Content-Type': mimetype,
'Content-Disposition': f'attachment; filename="{document.name}"',
}
)

How to test image upload API using postman? [duplicate]

I am using Spring MVC and this is my method:
/**
* Upload single file using Spring Controller.
*/
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public #ResponseBody ResponseEntity<GenericResponseVO<? extends IServiceVO>> uploadFileHandler(
#RequestParam("name") String name,
#RequestParam("file") MultipartFile file,
HttpServletRequest request,
HttpServletResponse response) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
// Creating the directory to store file
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "tmpFiles");
if (!dir.exists()) {
dir.mkdirs();
}
// Create the file on server
File serverFile = new File(dir.getAbsolutePath() + File.separator + name);
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile));
stream.write(bytes);
stream.close();
System.out.println("Server File Location=" + serverFile.getAbsolutePath());
return null;
} catch (Exception e) {
return null;
}
}
}
I need to pass the session id in postman and also the file. How can I do that?
In postman, set method type to POST.
Then select
Body -> form-data -> Enter your parameter name (file according to your code)
On the right side of the Key field, while hovering your mouse over it, there is a dropdown menu to select between Text/File. Select File, then a "Select Files" button will appear in the Value field.
For rest of "text" based parameters, you can post it like normally you do with postman. Just enter parameter name and select "text" from that right side dropdown menu and enter any value for it, hit send button. Your controller method should get called.
The Missing Visual Guide
You must first find the nearly-invisible pale-grey-on-white dropdown for File which is the magic key that unlocks the Choose Files button.
After you choose POST, then choose Body->form-data, then find the File dropdown, and then choose 'File', only then will the 'Choose Files' button magically appear:
Maybe you could do it this way:
Like this :
Body -> form-data -> select file
You must write "file" instead of "name"
Also you can send JSON data from Body -> raw field. (Just paste JSON string)
I got confused after seeing all of the answers, I couldn't find any proper screenshot to bring the Content Type column. After some time, I found it by my own. Hope this will help somebody like me.
Here is the steps:
click on red marked area of postman.
Now check the green marked option (Content Type).
Now change the search content type, in the yellow marked area.
In my case:
invoice_id_ls (key) contains the json data.
documents contains the file data.
placed_amount contains normal text string.
Select [Content Type] from [SHOW COLUMNS] then set content-type of "application/json" to the parameter of json text.
Don't give any headers.
Put your json data inside a .json file.
Select your both files one is your .txt file and other is .json file
for your request param keys.
If somebody wants to send json data in form-data format just need to declare the variables like this
Postman:
As you see, the description parameter will be in basic json format, result of that:
{ description: { spanish: 'hola', english: 'hello' } }
Kindly follow steps from top to bottom as shown in below image.
At third step you will find dropdown of type selection as shown in below image
Body > binary > Select File
If you need like
Upload file in multipart using form data and send json data(Dto object) in same POST Request
Get yor JSON object as String in Controller and make it Deserialize by adding this line
ContactDto contactDto = new ObjectMapper().readValue(yourJSONString, ContactDto.class);
If somebody needed:
body -> form-data
Add field name as array
Use below code in spring rest side :
#PostMapping(value = Constant.API_INITIAL + "/uploadFile")
public UploadFileResponse uploadFile(#RequestParam("file") MultipartFile file,String jsonFileVo) {
FileUploadVo fileUploadVo = null;
try {
fileUploadVo = new ObjectMapper().readValue(jsonFileVo, FileUploadVo.class);
} catch (Exception e) {
e.printStackTrace();
}
If you want to make a PUT request, just do everything as a POST request but add _method => PUT to your form-data parameters.
The way to send mulitpart data which containts a file with the json data is the following, we need to set the content-type of the respective json key fields to 'application/json' in the postman body tab like the following:
You can send both Image and optional/mandatory parameters.
In postman, there is Params tab.
I needed to pass both: a file and an integer. I did it this way:
needed to pass a file to upload:
did it as per Sumit's answer.
Request type : POST
Body -> form-data
under the heading KEY, entered the name of the variable ('file' in my backend code).
in the backend:
file = request.files['file']
Next to 'file', there's a drop-down box which allows you to choose between 'File' or 'Text'. Chose 'File' and under the heading VALUE, 'Select files' appeared. Clicked on this which opened a window to select the file.
2.
needed to pass an integer:
went to:
Params
entered variable name (e.g.: id) under KEY and its value (e.g.: 1) under VALUE
in the backend:
id = request.args.get('id')
Worked!
For each form data key you can set Content-Type, there is a postman button on the right to add the Content-Type column, and you don't have to parse a json from a string inside your Controller.
first, set post in method and fill link API
Then select Body -> form-data -> Enter your parameter name (file according to your code)
If you are using cookies to keep session, you can use interceptor to share cookies from browser to postman.
Also to upload a file you can use form-data tab under body tab on postman, In which you can provide data in key-value format and for each key you can select the type of value text/file. when you select file type option appeared to upload the file.
If you want the Id and File in one object you can add your request object to a method as standard and then within Postman set the Body to form-data and prefix your keys with your request object name. e.g. request.SessionId and request.File.
The steps of uploading a file through postman along with passing some input data is very well discussed in below blog along with the screenshot. In this blog, the api code is written in node js. You can go through it once to have more clarity.
https://jksnu.blogspot.com/2021/09/how-to-create-post-request-with.html
At Back-end part
Rest service in Controller will have mixed #RequestPart and MultipartFile to serve such Multipart + JSON request.
#RequestMapping(value = "/executesampleservice", method = RequestMethod.POST,
consumes = {"multipart/form-data"})
#ResponseBody
public boolean yourEndpointMethod(
#RequestPart("properties") #Valid ConnectionProperties properties,
#RequestPart("file") #Valid #NotNull #NotBlank MultipartFile file) {
return projectService.executeSampleService(properties, file);
}
At front-end :
formData = new FormData();
formData.append("file", document.forms[formName].file.files[0]);
formData.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
See in the image (POSTMAN request):
Click to view Postman request in form data for both file and json
To send image along with json data in postman you just have to follow the below steps .
Make your method to post in postman
go to the body section and click on form-data
provide your field name select file from the dropdown list as shown below
you can also provide your other fields .
now just write your image storing code in your controller as shown below .
postman :
my controller :
public function sendImage(Request $request)
{
$image=new ImgUpload;
if($request->hasfile('image'))
{
$file=$request->file('image');
$extension=$file->getClientOriginalExtension();
$filename=time().'.'.$extension;
$file->move('public/upload/userimg/',$filename);
$image->image=$filename;
}
else
{
return $request;
$image->image='';
}
$image->save();
return response()->json(['response'=>['code'=>'200','message'=>'image uploaded successfull']]);
}
That's it hope it will help you

What type of Request Data can be Retrieved from ColdFusion Headers?

This is a good way to grab the request before the response: useragent = getHttpRequestData().headers["User-Agent"];
What I noticed is that it will not grab the request unless it is on the actual list of header request. An example is I that it seems to only pull the basic request data. For instance if I set the cache control in the web.config file it does set cache, max age and etag, but when setting etags = getHttpRequestData().headers["ETag"]; and trying to output the data for the ETag generated by the web.config file/server it will not grab the ETag data to output. A few others that I tested are:
useragent = getHttpRequestData().headers["User-Agent"];
acceptencoding = getHttpRequestData().headers["Accept-Encoding"];
acceptlanugage = getHttpRequestData().headers["Accept-Language"];
cachecontrol = getHttpRequestData().headers["Cache-Control"];
connection = getHttpRequestData().headers["Connection"];
accept = getHttpRequestData().headers['Accept'];
contentlength = getHttpRequestData().headers['Content-Length'];
Request data is sent from the browser. You can see that with ColdFusion. But IIS sets response headers (such as etag) after ColdFusion is done processing. It's a response not a request. You cannot see that with ColdFusion, but you can in your browser. EX:

Uploading file Webservice

I'm trying to upload a file into my web service (written using DJango REST framework). I have written the following code but I get data can not be converted to utf-8 error
with open('/images/img.jpg', 'rb') as imgFile:
content = imgFile.read ()
json = { 'fileName': 'img.jpg', 'img': content}
json_data = simplejson.dumps(json)
reqURL = urllib2.Request("http://localhost:8000/uploadfile/",json_data)
opener = urllib2.build_opener()
f = opener.open(reqURL)
What is the right way of passing file content over JSON?
You don't send files like this. File contents are sent by embedding them inside the request body.
You may be better of by using the beautiful python-request library. Check out the file upload section.

HttpClient and extracting audio from server response

I am using Apache HttpClient to connect to a server for downloading a .wav file. I am using HTTP POST method in my program.
The server correctly responds with the following header and body:
> HTTP/1.1 200 OK\r\n Content-Disposition: attachment;
> filename=saveme1.mp3\r\n Content-Length: 6264\r\n
> Content-Transfer-Encoding: binary\r\n Content-Type: audio/mp3\r\n
How do I now extract the saveme1.mp3 file from the HTTP response? I am using the following code:
ResponseHandler<String> responseHandler = new BasicResponseHandler();
byte[] data = httpclient.execute(httppost, responseHandler).getBytes();
However, I am getting garbage when I am writing the data to a file.
FileOutputStream fileoutputstream = new FileOutputStream(outputFile);
for (int i = 0; i < data.length; i++)
fileoutputstream.write(data[i]);
If you want download mp3 I Think easiest way is :
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
Now you have entity and can call entity.getContent(); This give you you a inputStream , now you can save this stream with every method you want , ofcurse you need mime type and filename to save your file. if you have problem with filename and mime type tell me to add some sample code.
You are getting MIME attachment that you need to parse first. The BasicResponseHandler just return the response string, but you need the body of the attachment that contains the binary of your .mp3. You would need to do the following steps:
Understand the MIME format. You could skim the Wikipedia Entry for gaining quick familiarity
Once you understood, you need to create a MIME Parser. This would basically extract each part of the MIME message especially the body of your attachment. I think there should be something out there that you could reuse. You probably should look MimeMultipart. The only thing that I am not sure about it is whether it handles "binary" encoding in your message.
Create your own extension of ResponseHandler that will utilize the MIME Parser that you have in the previous step