Skip to content

Commit 74e9a8d

Browse files
Handle boundaries in multipart request (#927)
1 parent f13ac58 commit 74e9a8d

File tree

4 files changed

+141
-87
lines changed

4 files changed

+141
-87
lines changed

common/src/main/java/com/genexus/CommonUtil.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import java.math.BigDecimal;
1010
import java.io.*;
1111
import java.net.URLEncoder;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
14+
import java.nio.file.Paths;
1215
import java.text.*;
1316
import java.util.*;
1417

@@ -176,6 +179,62 @@ public Object initialValue()
176179
throw new ExceptionInInitializerError("GXUtil static constructor error: " + e.getMessage());
177180
}
178181
}
182+
183+
public static String getContentType(String fileName) {
184+
Path path = Paths.get(fileName);
185+
String defaultContentType = "application/octet-stream";
186+
187+
try {
188+
String probedContentType = Files.probeContentType(path);
189+
if (probedContentType == null || probedContentType.equals(defaultContentType))
190+
return findContentTypeByExtension(fileName);
191+
return probedContentType;
192+
} catch (IOException ioe) {
193+
return findContentTypeByExtension(fileName);
194+
}
195+
}
196+
197+
private static String findContentTypeByExtension(String fileName) {
198+
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
199+
String contentType = contentTypes.get(fileExtension);
200+
return contentType != null ? contentTypes.get(fileExtension) : "application/octet-stream";
201+
}
202+
203+
private static Map<String, String> contentTypes = new HashMap<String, String>() {{
204+
put("txt" , "text/plain");
205+
put("rtx" , "text/richtext");
206+
put("htm" , "text/html");
207+
put("html" , "text/html");
208+
put("xml" , "text/xml");
209+
put("aif" , "audio/x-aiff");
210+
put("au" , "audio/basic");
211+
put("wav" , "audio/wav");
212+
put("bmp" , "image/bmp");
213+
put("gif" , "image/gif");
214+
put("jpe" , "image/jpeg");
215+
put("jpeg" , "image/jpeg");
216+
put("jpg" , "image/jpeg");
217+
put("jfif" , "image/pjpeg");
218+
put("tif" , "image/tiff");
219+
put("tiff" , "image/tiff");
220+
put("png" , "image/x-png");
221+
put("3gp" , "video/3gpp");
222+
put("3g2" , "video/3gpp2");
223+
put("mpg" , "video/mpeg");
224+
put("mpeg" , "video/mpeg");
225+
put("mov" , "video/quicktime");
226+
put("qt" , "video/quicktime");
227+
put("avi" , "video/x-msvideo");
228+
put("exe" , "application/octet-stream");
229+
put("dll" , "application/x-msdownload");
230+
put("ps" , "application/postscript");
231+
put("pdf" , "application/pdf");
232+
put("svg" , "image/svg+xml");
233+
put("tgz" , "application/x-compressed");
234+
put("zip" , "application/x-zip-compressed");
235+
put("gz" , "application/x-gzip");
236+
put("json" , "application/json");
237+
}};
179238

180239
public static String removeAllQuotes(String fileName)
181240
{

common/src/main/java/com/genexus/internet/GXHttpClient.java

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -568,74 +568,81 @@ protected String setPathUrl(String url) {
568568
return url;
569569
}
570570

571+
572+
protected File fileToPost;
573+
protected String fileToPostName;
574+
571575
@SuppressWarnings("unchecked")
572576
protected byte[] getData()
573577
{
574578
byte[] out = new byte[0];
575579

576-
for (Object key: getVariablesToSend().keySet())
580+
for (Object key : getVariablesToSend().keySet())
577581
{
578-
String value = getMultipartTemplate().getFormDataTemplate((String)key, (String)getVariablesToSend().get(key));
579-
getContentToSend().add(0, value); //Variables al principio
582+
String value = getMultipartTemplate().getFormDataTemplate((String) key, (String) getVariablesToSend().get(key));
583+
getContentToSend().add(0, value); // Variables al principio
580584
}
581585

582586
for (int idx = 0; idx < getContentToSend().size(); idx++)
583587
{
584588
Object curr = getContentToSend().elementAt(idx);
585589

586-
if (curr instanceof String)
590+
if (curr instanceof String)
587591
{
588592
try
589593
{
590-
if(contentEncoding != null)
594+
if (contentEncoding != null)
591595
{
592-
out = addToArray(out, ((String)curr).getBytes(contentEncoding));
593-
}else
596+
out = addToArray(out, ((String) curr).getBytes(contentEncoding));
597+
} else
594598
{
595599
out = addToArray(out, (String) curr);
596600
}
597-
}catch(UnsupportedEncodingException e)
601+
} catch (UnsupportedEncodingException e)
598602
{
599603
System.err.println(e.toString());
600604
out = addToArray(out, (String) curr);
601605
}
602606
}
603-
else if (curr instanceof Object[])
607+
else if (curr instanceof Object[])
604608
{
605-
StringWriter writer = (StringWriter)((Object[])curr)[0];
606-
StringBuffer encoding = (StringBuffer)((Object[])curr)[1];
609+
StringWriter writer = (StringWriter) ((Object[]) curr)[0];
610+
StringBuffer encoding = (StringBuffer) ((Object[]) curr)[1];
607611

608-
if(encoding == null || encoding.length() == 0)
612+
if (encoding == null || encoding.length() == 0)
609613
{
610614
encoding = new StringBuffer("UTF-8");
611615
}
612616
try
613617
{
614618
out = addToArray(out, writer.toString().getBytes(encoding.toString()));
615619
}
616-
catch(UnsupportedEncodingException e)
620+
catch (UnsupportedEncodingException e)
617621
{
618622
out = addToArray(out, writer.toString());
619623
}
620624
}
621-
else if (curr instanceof byte[])
625+
else if (curr instanceof byte[])
622626
{
623627
out = addToArray(out, (byte[]) curr);
624628
}
625-
else //File or FormFile
629+
else // File or FormFile
626630
{
627631
File file;
628632
if (curr instanceof FormFile)
629633
{
630-
FormFile formFile = (FormFile)curr;
634+
FormFile formFile = (FormFile) curr;
631635
out = startMultipartFile(out, formFile.name, formFile.file);
632636
file = new File(formFile.file);
637+
fileToPostName = formFile.name;
633638
}
634639
else
635640
{
636641
file = (File) curr;
637642
}
638-
try (BufferedInputStream bis = new java.io.BufferedInputStream(new FileInputStream(file)))
643+
fileToPost = file;
644+
645+
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)))
639646
{
640647
out = addToArray(out, CommonUtil.readToByteArray(bis));
641648
}

gxcloudstorage-awss3-v2/src/main/java/com/genexus/db/driver/ExternalProviderS3V2.java

Lines changed: 3 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.apache.logging.log4j.Logger;
1818
import org.apache.logging.log4j.LogManager;
1919

20+
import com.genexus.CommonUtil;
2021
import com.genexus.util.GXService;
2122
import com.genexus.util.StorageUtils;
2223
import com.genexus.StructSdtMessages_Message;
@@ -292,62 +293,6 @@ public String copy(String objectUrl, String newName, String tableName, String fi
292293
copyWithoutACL(objectUrl, newName, tableName, fieldName);
293294
}
294295

295-
private String getContentType(String fileName) {
296-
Path path = Paths.get(fileName);
297-
String defaultContentType = "application/octet-stream";
298-
299-
try {
300-
String probedContentType = Files.probeContentType(path);
301-
if (probedContentType == null || probedContentType.equals(defaultContentType))
302-
return findContentTypeByExtension(fileName);
303-
return probedContentType;
304-
} catch (IOException ioe) {
305-
return findContentTypeByExtension(fileName);
306-
}
307-
}
308-
309-
private String findContentTypeByExtension(String fileName) {
310-
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
311-
String contentType = contentTypes.get(fileExtension);
312-
return contentType != null ? contentTypes.get(fileExtension) : "application/octet-stream";
313-
}
314-
315-
private static Map<String, String> contentTypes = new HashMap<String, String>() {{
316-
put("txt" , "text/plain");
317-
put("rtx" , "text/richtext");
318-
put("htm" , "text/html");
319-
put("html" , "text/html");
320-
put("xml" , "text/xml");
321-
put("aif" , "audio/x-aiff");
322-
put("au" , "audio/basic");
323-
put("wav" , "audio/wav");
324-
put("bmp" , "image/bmp");
325-
put("gif" , "image/gif");
326-
put("jpe" , "image/jpeg");
327-
put("jpeg" , "image/jpeg");
328-
put("jpg" , "image/jpeg");
329-
put("jfif" , "image/pjpeg");
330-
put("tif" , "image/tiff");
331-
put("tiff" , "image/tiff");
332-
put("png" , "image/x-png");
333-
put("3gp" , "video/3gpp");
334-
put("3g2" , "video/3gpp2");
335-
put("mpg" , "video/mpeg");
336-
put("mpeg" , "video/mpeg");
337-
put("mov" , "video/quicktime");
338-
put("qt" , "video/quicktime");
339-
put("avi" , "video/x-msvideo");
340-
put("exe" , "application/octet-stream");
341-
put("dll" , "application/x-msdownload");
342-
put("ps" , "application/postscript");
343-
put("pdf" , "application/pdf");
344-
put("svg" , "image/svg+xml");
345-
put("tgz" , "application/x-compressed");
346-
put("zip" , "application/x-zip-compressed");
347-
put("gz" , "application/x-gzip");
348-
put("json" , "application/json");
349-
}};
350-
351296
private String buildPath(String... pathPart) {
352297
ArrayList<String> pathParts = new ArrayList<>();
353298
for (String part : pathPart) {
@@ -701,7 +646,7 @@ private String copyWithACL(String objectUrl, String newName, String tableName, S
701646
.bucket(bucket)
702647
.key(resourceKey)
703648
.metadata(metadata)
704-
.contentType(getContentType(newName));
649+
.contentType(CommonUtil.getContentType(newName));
705650
if (endpointUrl.contains(".amazonaws.com"))
706651
putObjectRequestBuilder = putObjectRequestBuilder.acl(internalToAWSACLWithACL(acl));
707652
PutObjectRequest putObjectRequest = putObjectRequestBuilder.build();
@@ -821,7 +766,7 @@ private String copyWithoutACL(String objectUrl, String newName, String tableName
821766
.bucket(bucket)
822767
.key(resourceKey)
823768
.metadata(metadata)
824-
.contentType(getContentType(newName));
769+
.contentType(CommonUtil.getContentType(newName));
825770
PutObjectRequest putObjectRequest = putObjectRequestBuilder.build();
826771
client.putObject(putObjectRequest, RequestBody.fromBytes(objectBytes.asByteArray()));
827772

java/src/main/java/com/genexus/internet/HttpClientJavaLib.java

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -511,24 +511,67 @@ public void execute(String method, String url) {
511511
HttpPost httpPost = new HttpPost(url.trim());
512512
httpPost.setConfig(reqConfig);
513513
Set<String> keys = getheadersToSend().keySet();
514-
boolean hasConentType = false;
514+
boolean hasContentType = false;
515+
515516
for (String header : keys) {
516517
httpPost.addHeader(header, getheadersToSend().get(header));
517-
if (header.equalsIgnoreCase("Content-type"))
518-
hasConentType = true;
518+
if (header.equalsIgnoreCase("Content-Type")) {
519+
hasContentType = true;
520+
}
519521
}
520-
if (!hasConentType) // Si no se setea Content-type, se pone uno default
521-
httpPost.addHeader("Content-type", "application/x-www-form-urlencoded");
522522

523-
ByteArrayEntity dataToSend;
524-
if (!getIsMultipart() && getVariablesToSend().size() > 0)
525-
dataToSend = new ByteArrayEntity(CommonUtil.hashtable2query(getVariablesToSend()).getBytes());
526-
else
527-
dataToSend = new ByteArrayEntity(getData());
528-
httpPost.setEntity(dataToSend);
523+
if (getIsMultipart()) {
524+
if (!hasContentType) {
525+
httpPost.addHeader("Content-Type", "multipart/form-data");
526+
}
529527

530-
response = httpClient.execute(httpPost, httpClientContext);
528+
String boundary = "----Boundary" + System.currentTimeMillis();
529+
httpPost.removeHeaders("Content-Type");
530+
httpPost.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
531531

532+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
533+
534+
for (Map.Entry<String, String> entry : ((Map<String, String>) getVariablesToSend()).entrySet()) {
535+
if ("fileFieldName".equals(entry.getKey())) {
536+
continue;
537+
}
538+
bos.write(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8));
539+
bos.write(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n").getBytes(StandardCharsets.UTF_8));
540+
bos.write(entry.getValue().getBytes(StandardCharsets.UTF_8));
541+
bos.write("\r\n".getBytes(StandardCharsets.UTF_8));
542+
}
543+
if (getData() != null && getData().length > 0) {
544+
String fileFieldName = getVariablesToSend().containsKey("fileFieldName") ?
545+
(String) getVariablesToSend().get("fileFieldName") : fileToPostName;
546+
String fileName = fileToPost != null ? fileToPost.getName() : "uploadedFile";
547+
String contentType = fileToPost != null ? CommonUtil.getContentType(fileName) : "application/octet-stream";
548+
549+
bos.write(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8));
550+
bos.write(("Content-Disposition: form-data; name=\"" + fileFieldName + "\"; filename=\"" + fileName + "\"\r\n").getBytes(StandardCharsets.UTF_8));
551+
bos.write(("Content-Type: " + contentType + "\r\n\r\n").getBytes(StandardCharsets.UTF_8));
552+
bos.write(getData());
553+
bos.write("\r\n".getBytes(StandardCharsets.UTF_8));
554+
}
555+
556+
bos.write(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8));
557+
ByteArrayEntity dataToSend = new ByteArrayEntity(bos.toByteArray());
558+
httpPost.setEntity(dataToSend);
559+
} else {
560+
if (!hasContentType) {
561+
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
562+
}
563+
564+
ByteArrayEntity dataToSend;
565+
if (getVariablesToSend().size() > 0) {
566+
String formData = CommonUtil.hashtable2query(getVariablesToSend());
567+
dataToSend = new ByteArrayEntity(formData.getBytes(StandardCharsets.UTF_8));
568+
} else {
569+
dataToSend = new ByteArrayEntity(getData());
570+
}
571+
httpPost.setEntity(dataToSend);
572+
}
573+
574+
response = httpClient.execute(httpPost, httpClientContext);
532575
} else if (method.equalsIgnoreCase("PUT")) {
533576
HttpPut httpPut = new HttpPut(url.trim());
534577
httpPut.setConfig(reqConfig);

0 commit comments

Comments
 (0)